From: Gert Wollny Date: Fri, 9 Apr 2021 07:46:34 +0000 (+0200) Subject: New upstream version 3.6.6 X-Git-Tag: archive/raspbian/3.6.9-4+rpi1^2~26^2~6 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22Program/%22http:/www.example.com/cgi/%22https:/%22Program?a=commitdiff_plain;h=051f9a6aea967d80a072c0c38798e9082e0b2253;p=dcmtk.git New upstream version 3.6.6 --- diff --git a/ANNOUNCE b/ANNOUNCE index f4d40abd..9a4534be 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,16 +1,14 @@ ANNOUNCEMENT -Version 3.6.5 of the OFFIS DCMTK (DICOM ToolKit) software is now available for -public release. This is a minor release that includes the following changes -over the previous version 3.6.4: +Version 3.6.6 of the OFFIS DCMTK (DICOM ToolKit) software is now available for +public release. This release includes the following main changes over the +previous version 3.6.5: -- DCMTK 3.6.5 builds correctly on older and up-to-date versions of GNU gcc - (4.4.7 to 9.2.0), Clang (3.4.2 to 9.0.0), AppleClang (11.0.0), Microsoft - Visual Studio (2008 to 2019), SunPro CC (5.14 and 5.15) and IBM XL C/C++ - (16.1.1.3). +- DCMTK 3.6.6 builds correctly on older and up-to-date versions of GNU gcc + (4.2.1 to 10.2.0) Clang (3.4.2 to 11.0.0), Apple Clang 11.0.0, + Microsoft Visual Studio (2008 to 2019) and SunPro CC (5.14 and 5.15). - Tested with the following operating systems/environments: - - Android on arm64 - Cygwin on x86_64 - FreeBSD on x86_64 @@ -20,134 +18,94 @@ over the previous version 3.6.4: - OpenBSD on x86_64 - OpenIndiana on x86 - Solaris on x86 - - Windows (and MinGW) on x86_64 and x86 + - Windows (including MinGW and Cygwin) on x86_64 and x86 For a complete list of tested systems and compilers, see the INSTALL file. -- GNU Autoconf is still deprecated, running 'configure' emits a warning by - default. Support for GNU Autoconf will be removed after this release. - -- Updated data dictionary, SOP Class, Frame of Reference and Transfer Syntax - UIDs for the recently approved changes to the DICOM standard (i.e. Supplements - and CPs), up to DICOM standard release DICOM 2019c plus Supplement 175 (Second - Generation Radiotherapy - C-Arm RT Treatment Modalities). - -- Added support for directory record "RADIOTHERAPY" that has been introduced - with Supplement 147 (Second Generation Radiotherapy - Prescription and Segment - Annotation). - -- Added support for the three new 64-bit integer VRs introduced with CP-1819: - Other 64-bit Very Long (OV), Signed 64-bit Very Long (SV) and Unsigned 64-bit - Very Long (UV). - -- Implemented support for the Extended BCP 195 TLS Profile, introduced with - Supplement 206, in the dcmtls module and the various TLS-enabled DCMTK tools. - -- Added option to "storescu" to rename files after processing them by appending - ".bad" or ".good" at the end of the filename. - -- Added new options to "wlmscpfs" that allow for dumping incoming C-FIND - requests to text files using a configurable directory and filename. - -- Updated automatically generated Context Group classes in "dcmsr" - (Structured Reporting) based on DICOM 2019c. Also updated the Code - definitions from the supported coding schemes such as DICOM, NCIt and UMLS. - -- Further enhanced DICOM Structured Reporting (SR) module "dcmsr": - - - Added support for the Performed Imaging Agent Administration SR IOD and the - Planned Imaging Agent Administration SR IOD introduced with Supplement 164. +- Updated data dictionary, SOP classes, well-known frame of references, + transfer syntaxes, code definitions and supported context group classes for + DICOM standard release 2020e. - - Added support for the Synchronization Module, which is required for some SR - IODs, e.g. Procedure Log SR or Performed Imaging Agent Administration SR. +- Added new DCMTK module dcmect, which facilitates creation, loading, (partly) + modification and storing Enhanced CT objects: - - Added initial support for coding scheme "SCT" (SNOMED CT) by defining those - CODE_SCT_xxx code constants that are needed for the "cmr" submodule. + - Also included is a general Concatenation API that allows for creating and + re-assembling Concatenations from given DICOM datasets. Right now, only + uncompressed ("unencapsulated") pixel data is supported. - - Updated SR Template classes from DCMR for the 2019b edition of the DICOM - standard, i.e. all SRT (SNOMED RT) codes were replaced by their associated - SCT (SNOMED CT) counterparts. This change was introduced with CP-1850. + - The existing Segmentation API (dcmseg) as well as the new Enhanced CT API + (dcmect) both support writing and reading Concatenations via dedicated + methods. - - Added new print flag PF_printEmptyCodes, which prints the text "empty code" - for empty codes instead of "invalid code". This new flag is e.g. used for - the output stream operator of the DSRCodedEntryValue class. + - Thanks to GE Aviation for sponsoring this feature. -- The list of elliptic curves to be negotiated as part of a TLS is now created - dynamically, i.e. it is tested at runtime which elliptic curves are supported - by the installed OpenSSL library. +- Major revision of JSON export tool (dcm2json), which should now be fully + standard compliant. -- Allow disabling Functional Group checks when writing Segmentations and - Parametric Map objects in order to speed up writing objects with many frames. +- Major revision of the dcmsign module, which now supports Elliptic Curve + (ECDSA) signatures, the DICOM SR RSA Digital Signature Profile, and CRLs in + hashed certificate directories. During signature verification the chain of + trust for the signer certificates are now fully checked and there is limited + support for the creation and verification of trusted timestamps. -- Added macro that enables the wide char (wchar_t*) support of the XML parser - that is part of the DCMTK (ofstd/ofxml). This support is limited to Windows - systems and still regarded as experimental (see documentation for details). +- Added support for the Rendition Selection Document IOD, which has been + introduced with Supplement 202 (Real-Time Video), to the dcmsr module. -- The tool "findscu" now always returns with a non-zero exit code when an error - occurred, e.g. when association negotiation failed. +- Added support for the new Waveform Storage SOP Classes that have been + introduced with Supplement 217 (Neurophysiology Waveforms) to the DICOMDIR + generation code and to the dcmsr module. -- CMake-related enhancements: +- Added support for the new 2nd generation RT Storage SOP Classes that have + been introduced with Supplement 175, 176 and 199, as well as for the new + Encapsulated OBJ and MTL Storage SOP Classes (Supplement 208) to the + DICOMDIR generation code. - - DCMTK now understands and makes use of the CMake variable CMAKE_CXX_STANDARD - when a CMake version that supports it is employed (CMake 3.1.3 and newer). +- Added TLS support to the DcmSCP and DcmSCPPool classes and to the dcmrecv + command line tool. - - Added CMake option that controls whether DCMTK gets compiled using the - multi-threaded static or DLL runtime library when using MSVC on Windows. +- Updated and completely revised DIMSE Status Code definitions. Now, the + definitions and also the log output are consistent with the current edition + of the DICOM standard. -- Various fixes and extensions to the JPEG-LS implementation: +- Significant performance enhancements for code that gets an item from or + inserts an item into a sequence with a large number of items. - - Added command line options controlling how odd-length bitstreams are - padded to even length (for compatibility with HP LOCO). +- DCMTK now successfully compiles when UNICODE/_UNICODE is defined on Windows. - - Added command line option that causes the decoder to store images even - though an error occurred during the decoding process, which may be helpful - for slightly truncated bitstreams. +- When compiling on Windows, new CMake options can now be used to control the + Win32 build model (multi-threaded or multi-threaded DLL). - - Enable setting of individual JPEG-LS encoding parameters - T1, T2, T3 and RESET. - - - Various bugfixes in JPEG-LS encoder and decoder. - -- Fixed binary Segmentation object creation when width is not dividable by 8. - -- Fixed wrong DIMSE status codes A8xx (for C-STORE and C-FIND) and A800 (for - C-GET and C-MOVE), which were never defined in the official DICOM standard. - Now, the DCMTK uses the correct DIMSE status code 0122H for "SOP Class not - supported" for all DIMSE messages. - -- Fixed various issues that occurred after the official 3.6.4 release. +- Fixed various issues that occurred after the official 3.6.5 release. See CHANGES file for details. - Many people have contributed to this new release of DCMTK, appearing here in alphabetical order. Thank you very much for your support! - Victor Derks - Chinna Durai - Holger Franke - Sergei Gordey - Daniel Grieger - Bengt Gustafsson - Alexander Haderer + Michel Amat (GitHub user "amatm") + Bartosz Bialoskorski + Jesper Bojesen + Marcel Claus + Jake Cobb + Martin Czarnowski + Matthias Gierlings + Niklas Johansson (GitHub user "Raphexion") + Andreas Keizers Peter Klotz - Brian Lucas - Mathieu Malaterre - Hans Meine + Damien Lerat + Mathieu Malaterre + Robert Mulcahey + Maria Nedyak + Steve Pieper + Sergey Razuvaev + Markus Sabin Maria Samoylova - Martin Wenger - Brian Wise - Grischa Zengel + Adrian Schmidt-Foehre + Waldo Valenzuela - Andreas Gravgaard Andersen (GitHub user "agravgaard") - Hans Johnson (GitHub user "hjmjohnson") - Stefano Magni + DCMTK forum users "CStarkey", "JustSomeGuy", "Shaeto", and "ruben.cruz" + GitHub user "iboB" - Forum user "AlexanderLysenko" - GitHub user "eborisch" - GitHub user "FreddyFunk" - -Members of the DCMTK Team who have worked on this release are -(in alphabetical order): +Members of the DCMTK Team who have worked on this release are: Pedro Arizpe Gomez Marco Eichelberg @@ -155,15 +113,8 @@ Members of the DCMTK Team who have worked on this release are Joerg Riesmeier Jan Schlamelcher -Student associates: - - Nikolas Goldhammer - -Also see CREDITS file for projects and companies who have been generously -supporting DCMTK. - The DCMTK software can be downloaded via: https://dicom.offis.de/dcmtk or https://www.dcmtk.org/ -OFFIS e.V., Oldenburg, Germany, 2019-10-28 +OFFIS e.V., Oldenburg, Germany, 2021-01-14 diff --git a/CHANGES b/CHANGES index b7fc0655..488e8438 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,13 @@ In earlier versions of DCMTK, changes between releases had been documented in a -CHANGES.XXX file inside DCMTK's main directory. +CHANGES.XXX file inside DCMTK's main directory, with "XXX" referring to the +version number of the release. -Now, the CHANGES.XXX file has been moved to the dcmtk/doc folder with the latest -one being updated every time that a new DCMTK version is released. Thus it -always contains all DCMTK changes between the last DCMTK release and the most -recent one. +Now, the CHANGES.XXX file has been moved to the dcmtk/docs folder (in the +source code package) with the latest one being updated every time a new DCMTK +version is released. Thus, it always contains all DCMTK changes between the +previous DCMTK release and the most recent one. For very recent changes, i. e. those changes to DCMTK that have been applied -after the most recent release, see the DCMTK git repository log at -http://git.dcmtk.org/ . +after the most recent release, see the commit history of DCMTK's git repository +at https://git.dcmtk.org/. diff --git a/CMake/3rdparty.cmake b/CMake/3rdparty.cmake index 4a388aaf..43aa282e 100644 --- a/CMake/3rdparty.cmake +++ b/CMake/3rdparty.cmake @@ -1,188 +1,24 @@ -if(WIN32 AND NOT MINGW) - +set(USE_FIND_PACKAGE_DOCS "Control whether libraries are searched via CMake's find_package() mechanism or a Windows specific fallback") +if(WIN32) # For Windows, we don't used FIND_PACKAGE because DCMTK usually is used with its # own set of 3rd-party support libraries that can be downloaded from DCMTK's # website (pre-built). - - # libxml support: find out whether user has library - file(GLOB LIBXML_DIR "${DCMTK_SOURCE_DIR}/../libxml2*") - find_path(WITH_LIBXMLINC "/include/libxml/parser.h" "${LIBXML_DIR}" NO_DEFAULT_PATH) - - # libpng support: find out whether user has library - file(GLOB LIBPNG_DIR "${DCMTK_SOURCE_DIR}/../libpng*") - find_path(WITH_LIBPNGINC "include/png.h" "${LIBPNG_DIR}" NO_DEFAULT_PATH) - - # libtiff support: find out whether user has library - file(GLOB LIBTIFF_DIR "${DCMTK_SOURCE_DIR}/../libtiff*") - find_path(WITH_LIBTIFFINC "include/tiff.h" "${LIBTIFF_DIR}" NO_DEFAULT_PATH) - - # OpenSSL support: find out whether user has library - file(GLOB OPENSSL_DIR "${DCMTK_SOURCE_DIR}/../openssl*") - find_path(WITH_OPENSSLINC "include/openssl/ssl.h" "${OPENSSL_DIR}" NO_DEFAULT_PATH) - - # zlib support: find out whether user has library - file(GLOB ZLIB_DIR "${DCMTK_SOURCE_DIR}/../zlib*") - find_path(WITH_ZLIBINC "include/zlib.h" "${ZLIB_DIR}" NO_DEFAULT_PATH) - - # sndfile support: find out whether user has library. Needed for module dcmwave (not in public DCMTK yet, marked as advanced) - file(GLOB SNDFILE_DIR "${DCMTK_SOURCE_DIR}/../libsndfile*") - find_path(WITH_SNDFILEINC "sndfile.h" "${SNDFILE_DIR}" NO_DEFAULT_PATH) - mark_as_advanced(SNDFILE_DIR WITH_SNDFILEINC) - - # libiconv support: find out whether user has library - file(GLOB LIBICONV_DIR "${DCMTK_SOURCE_DIR}/../libiconv*") - find_path(WITH_LIBICONVINC "include/iconv.h" "${LIBICONV_DIR}" NO_DEFAULT_PATH) - - # OpenJPEG support: find out whether user has library - file(GLOB OPENJPEG_DIR "${DCMTK_SOURCE_DIR}/../openjpeg*") - find_path(WITH_OPENJPEGINC "lib/openjp2_o.lib" "${OPENJPEG_DIR}" NO_DEFAULT_PATH) - - # libxml support: configure compiler - if(DCMTK_WITH_XML) - if(WITH_LIBXMLINC) - set(LIBXML_INCDIR "${WITH_LIBXMLINC}/include") - set(LIBXML_LIBDIR "${WITH_LIBXMLINC}/lib") - set(LIBXML_LIBS debug "${LIBXML_LIBDIR}/libxml2_d.lib" optimized "${LIBXML_LIBDIR}/libxml2_o.lib" debug "${LIBXML_LIBDIR}/iconv_d.lib" optimized "${LIBXML_LIBDIR}/iconv_o.lib") - message(STATUS "Info: DCMTK XML support will be enabled") - set(WITH_LIBXML 1) - # this hides some warnings that are emitted when linking against libxmlXXX.lib instead of linking the DLL directly - add_definitions("-DLIBXML_STATIC") - else() # turn off library if library path not set - message(STATUS "Warning: XML support will be disabled because libxml2 directory is not specified. Correct path and re-enable DCMTK_WITH_XML.") - set(DCMTK_WITH_XML OFF CACHE BOOL "" FORCE) - set(WITH_LIBXML "") - endif() - endif() - - # libpng support: configure compiler - if(DCMTK_WITH_PNG) - if(WITH_LIBPNGINC) - set(LIBPNG_INCDIR "${WITH_LIBPNGINC}/include") - set(LIBPNG_LIBDIR "${WITH_LIBPNGINC}/lib") - set(LIBPNG_LIBS debug "${LIBPNG_LIBDIR}/libpng_d.lib" optimized "${LIBPNG_LIBDIR}/libpng_o.lib") - message(STATUS "Info: DCMTK PNG support will be enabled") - set(WITH_LIBPNG 1) - else() # turn off library if library path not set - message(STATUS "Warning: PNG support will be disabled because libpng directory was not specified. Correct path and re-enable DCMTK_WITH_PNG.") - set(DCMTK_WITH_PNG OFF CACHE BOOL "" FORCE) - set(WITH_LIBPNG "") - endif() - endif() - - # libtiff support: configure compiler - if(DCMTK_WITH_TIFF) - if(WITH_LIBTIFFINC) - set(LIBTIFF_INCDIR "${WITH_LIBTIFFINC}/include") - set(LIBTIFF_LIBDIR "${WITH_LIBTIFFINC}/lib") - set(LIBTIFF_LIBS debug "${LIBTIFF_LIBDIR}/libtiff_d.lib" optimized "${LIBTIFF_LIBDIR}/libtiff_o.lib") - message(STATUS "Info: DCMTK TIFF support will be enabled") - set(WITH_LIBTIFF 1) - else() # turn off library if library path not set - message(STATUS "Warning: TIFF support will be disabled because libtiff directory was not specified. Correct path and re-enable DCMTK_WITH_TIFF.") - set(DCMTK_WITH_TIFF OFF CACHE BOOL "" FORCE) - set(WITH_LIBTIFF "") - endif() - endif() - - # OpenSSL support: configure compiler - if(DCMTK_WITH_OPENSSL) - if(WITH_OPENSSLINC) - include(CheckCXXSourceCompiles) - set(OPENSSL_BINDIR "${WITH_OPENSSLINC}/bin") - set(OPENSSL_INCDIR "${WITH_OPENSSLINC}/include") - set(OPENSSL_LIBDIR "${WITH_OPENSSLINC}/lib") - # starting with OpenSSL 1.1.0, the Windows crypt32 library is needed for a static link of OpenSSL. - set(OPENSSL_LIBS "crypt32" debug "${OPENSSL_LIBDIR}/dcmtkssl_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkssl_o.lib" debug "${OPENSSL_LIBDIR}/dcmtkcrypto_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkcrypto_o.lib") - set(TEMP_INCLUDES "${CMAKE_REQUIRED_INCLUDES}") - list(APPEND CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCDIR}") - CHECK_CXX_SOURCE_COMPILES("extern \"C\" {\n#include \n}\nint main(){\n#if OPENSSL_VERSION_NUMBER < 0x10001000L\n#error OpenSSL too old\n#endif\n}\n" OPENSSL_VERSION_CHECK) - set(CMAKE_REQUIRED_INCLUDES "${TEMP_INCLUDES}") - if(OPENSSL_VERSION_CHECK) - message(STATUS "Info: DCMTK OPENSSL support will be enabled") - set(WITH_OPENSSL 1) - else() - message(STATUS "Info: DCMTK OPENSSL support will be disabled: DCMTK requires OpenSSL version 1.0.1 or newer") - set(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) - set(WITH_OPENSSL "") - endif() - else() # turn off library if library path not set - message(STATUS "Warning: OPENSSL support will be disabled because openssl directory was not specified. Correct path and re-enable DCMTK_WITH_OPENSSL.") - set(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) - set(WITH_OPENSSL "") - endif() - endif() - - # zlib support: configure compiler - if(DCMTK_WITH_ZLIB) - if(WITH_ZLIBINC) - set(ZLIB_INCDIR "${WITH_ZLIBINC}/include") - set(ZLIB_LIBDIR "${WITH_ZLIBINC}/lib") - set(ZLIB_LIBS debug "${ZLIB_LIBDIR}/zlib_d.lib" optimized "${ZLIB_LIBDIR}/zlib_o.lib") - message(STATUS "Info: DCMTK ZLIB support will be enabled") - set(WITH_ZLIB 1) - else() # turn off library if library path not set - message(STATUS "Warning: ZLIB support will be disabled because zlib directory was not specified. Correct path and re-enable DCMTK_WITH_ZLIB.") - set(DCMTK_WITH_ZLIB OFF CACHE BOOL "" FORCE) - set(WITH_ZLIB "") - endif() - endif() - - # sndfile support: configure compiler - if(DCMTK_WITH_SNDFILE) - if(WITH_SNDFILEINC) - set(SNDFILE_INCDIR "${WITH_SNDFILEINC}/include") - set(SNDFILE_LIBDIR "${WITH_SNDFILEINC}/lib") - set(SNDFILE_LIBS debug "${SNDFILE_LIBDIR}/libsndfile_d.lib" optimized "${SNDFILE_LIBDIR}/libsndfile_o.lib") - message(STATUS "Info: DCMTK SNDFILE support will be enabled") - set(WITH_SNDFILE 1) - else() # turn off library if library path not set - message(STATUS "Warning: SNDFILE support will be disabled because libsndfile directory was not specified. Correct path and re-enable DCMTK_WITH_SNDFILE.") - set(DCMTK_WITH_SNDFILE OFF CACHE BOOL "" FORCE) - set(WITH_SNDFILE "") - endif() - endif() - - # libiconv support: configure compiler - if(DCMTK_WITH_ICONV) - if(WITH_LIBICONVINC) - set(LIBICONV_INCDIR "${WITH_LIBICONVINC}/include") - set(LIBICONV_LIBDIR "${WITH_LIBICONVINC}/lib") - set(LIBICONV_LIBS debug "${LIBICONV_LIBDIR}/libiconv_d.lib" optimized "${LIBICONV_LIBDIR}/libiconv_o.lib") - message(STATUS "Info: DCMTK ICONV support will be enabled") - set(WITH_LIBICONV 1) - else() # turn off library if library path not set - message(STATUS "Warning: ICONV support will be disabled because libiconv directory was not specified. Correct path and re-enable DCMTK_WITH_ICONV.") - set(DCMTK_WITH_ICONV OFF CACHE BOOL "" FORCE) - set(WITH_LIBICONV "") - endif() + if(MINGW) + set(DCMTK_USE_FIND_PACKAGE TRUE CACHE BOOL "${USE_FIND_PACKAGE_DOCS}") + else() + set(DCMTK_USE_FIND_PACKAGE FALSE CACHE BOOL "${USE_FIND_PACKAGE_DOCS}") endif() - - # OpenJPEG support: configure compiler - if(DCMTK_WITH_OPENJPEG) - if(WITH_OPENJPEGINC) - # Unfortunately, OpenJPEG uses a version number in the include path. This needs special handling. - file(GLOB OPENJPEG2_DIR "${WITH_OPENJPEGINC}/include/openjpeg*") - find_path(WITH_OPENJPEGINC1 "openjpeg.h" "${OPENJPEG2_DIR}" NO_DEFAULT_PATH) - if ("${WITH_OPENJPEGINC1}" STREQUAL "WITH_OPENJPEGINC1-NOTFOUND") - message(STATUS "Info: DCMTK OpenJPEG support will be disabled because the header files were not found.") - set(DCMTK_WITH_OPENJPEG OFF CACHE BOOL "" FORCE) - set(WITH_OPENJPEG "") - else() - set(OPENJPEG_INCDIR "${WITH_OPENJPEGINC1}") - set(OPENJPEG_LIBDIR "${WITH_OPENJPEGINC}/lib") - set(OPENJPEG_LIBS debug "${OPENJPEG_LIBDIR}/openjp2_d.lib" optimized "${OPENJPEG_LIBDIR}/openjp2_o.lib") - message(STATUS "Info: DCMTK OpenJPEG support will be enabled") - set(WITH_OPENJPEG 1) - endif() - else() # turn off library if library path not set - message(STATUS "Warning: OpenJPEG support will be disabled because openjpeg directory was not specified. Correct path and re-enable DCMTK_WITH_OPENJPEG.") - set(DCMTK_WITH_OPENJPEG OFF CACHE BOOL "" FORCE) - set(WITH_OPENJPEG "") - endif() +else() + # Only find_package is supported + set(DCMTK_USE_FIND_PACKAGE TRUE CACHE BOOL "${USE_FIND_PACKAGE_DOCS}") + if(NOT DCMTK_USE_FIND_PACKAGE) + message(WARNING "Only find_package is supported on this platform, overriding user setting of DCMTK_USE_FIND_PACKAGE.") + set(DCMTK_USE_FIND_PACKAGE TRUE FORCE) endif() +endif() +mark_as_advanced(DCMTK_USE_FIND_PACKAGE) -else(WIN32 AND NOT MINGW) - +if(DCMTK_USE_FIND_PACKAGE) # Find TIFF if(DCMTK_WITH_TIFF) find_package(TIFF QUIET) @@ -356,8 +192,189 @@ else(WIN32 AND NOT MINGW) set(OPENJPEG_LIBS ${OPENJPEG_LIBRARIES}) endif() endif() +else() + if(NOT DEFINED DCMTK_SUPPORT_LIBRARIES_DIR) + get_filename_component(DCMTK_SUPPORT_LIBRARIES_DIR "${DCMTK_SOURCE_DIR}" PATH) + set(DCMTK_SUPPORT_LIBRARIES_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}" CACHE PATH "The directory to search for precompiled DCMTK support libraries.") + endif() + + # libxml support: find out whether user has library + file(GLOB LIBXML_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/libxml2*") + find_path(WITH_LIBXMLINC "${DCMTK_SUPPORT_LIBRARIES_DIR}/include/libxml/parser.h" "${LIBXML_DIR}" NO_DEFAULT_PATH) + + # libpng support: find out whether user has library + file(GLOB LIBPNG_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/libpng*") + find_path(WITH_LIBPNGINC "include/png.h" "${LIBPNG_DIR}" NO_DEFAULT_PATH) + + # libtiff support: find out whether user has library + file(GLOB LIBTIFF_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/libtiff*") + find_path(WITH_LIBTIFFINC "include/tiff.h" "${LIBTIFF_DIR}" NO_DEFAULT_PATH) + + # OpenSSL support: find out whether user has library + file(GLOB OPENSSL_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/openssl*") + find_path(WITH_OPENSSLINC "include/openssl/ssl.h" "${OPENSSL_DIR}" NO_DEFAULT_PATH) + + # zlib support: find out whether user has library + file(GLOB ZLIB_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/zlib*") + find_path(WITH_ZLIBINC "include/zlib.h" "${ZLIB_DIR}" NO_DEFAULT_PATH) + + # sndfile support: find out whether user has library. Needed for module dcmwave (not in public DCMTK yet, marked as advanced) + file(GLOB SNDFILE_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/libsndfile*") + find_path(WITH_SNDFILEINC "sndfile.h" "${SNDFILE_DIR}" NO_DEFAULT_PATH) + mark_as_advanced(SNDFILE_DIR WITH_SNDFILEINC) + + # libiconv support: find out whether user has library + file(GLOB LIBICONV_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/libiconv*") + find_path(WITH_LIBICONVINC "include/iconv.h" "${LIBICONV_DIR}" NO_DEFAULT_PATH) -endif(WIN32 AND NOT MINGW) + # OpenJPEG support: find out whether user has library + file(GLOB OPENJPEG_DIR "${DCMTK_SUPPORT_LIBRARIES_DIR}/openjpeg*") + find_path(WITH_OPENJPEGINC "lib/openjp2_o.lib" "${OPENJPEG_DIR}" NO_DEFAULT_PATH) + + # libxml support: configure compiler + if(DCMTK_WITH_XML) + if(WITH_LIBXMLINC) + set(LIBXML_INCDIR "${WITH_LIBXMLINC}/include") + set(LIBXML_LIBDIR "${WITH_LIBXMLINC}/lib") + set(LIBXML_LIBS debug "${LIBXML_LIBDIR}/libxml2_d.lib" optimized "${LIBXML_LIBDIR}/libxml2_o.lib" debug "${LIBXML_LIBDIR}/iconv_d.lib" optimized "${LIBXML_LIBDIR}/iconv_o.lib") + message(STATUS "Info: DCMTK XML support will be enabled") + set(WITH_LIBXML 1) + # this hides some warnings that are emitted when linking against libxmlXXX.lib instead of linking the DLL directly + add_definitions("-DLIBXML_STATIC") + else() # turn off library if library path not set + message(STATUS "Warning: XML support will be disabled because libxml2 directory is not specified. Correct path and re-enable DCMTK_WITH_XML.") + set(DCMTK_WITH_XML OFF CACHE BOOL "" FORCE) + set(WITH_LIBXML "") + endif() + endif() + + # libpng support: configure compiler + if(DCMTK_WITH_PNG) + if(WITH_LIBPNGINC) + set(LIBPNG_INCDIR "${WITH_LIBPNGINC}/include") + set(LIBPNG_LIBDIR "${WITH_LIBPNGINC}/lib") + set(LIBPNG_LIBS debug "${LIBPNG_LIBDIR}/libpng_d.lib" optimized "${LIBPNG_LIBDIR}/libpng_o.lib") + message(STATUS "Info: DCMTK PNG support will be enabled") + set(WITH_LIBPNG 1) + else() # turn off library if library path not set + message(STATUS "Warning: PNG support will be disabled because libpng directory was not specified. Correct path and re-enable DCMTK_WITH_PNG.") + set(DCMTK_WITH_PNG OFF CACHE BOOL "" FORCE) + set(WITH_LIBPNG "") + endif() + endif() + + # libtiff support: configure compiler + if(DCMTK_WITH_TIFF) + if(WITH_LIBTIFFINC) + set(LIBTIFF_INCDIR "${WITH_LIBTIFFINC}/include") + set(LIBTIFF_LIBDIR "${WITH_LIBTIFFINC}/lib") + set(LIBTIFF_LIBS debug "${LIBTIFF_LIBDIR}/libtiff_d.lib" optimized "${LIBTIFF_LIBDIR}/libtiff_o.lib") + message(STATUS "Info: DCMTK TIFF support will be enabled") + set(WITH_LIBTIFF 1) + else() # turn off library if library path not set + message(STATUS "Warning: TIFF support will be disabled because libtiff directory was not specified. Correct path and re-enable DCMTK_WITH_TIFF.") + set(DCMTK_WITH_TIFF OFF CACHE BOOL "" FORCE) + set(WITH_LIBTIFF "") + endif() + endif() + + # OpenSSL support: configure compiler + if(DCMTK_WITH_OPENSSL) + if(WITH_OPENSSLINC) + include(CheckCXXSourceCompiles) + set(OPENSSL_BINDIR "${WITH_OPENSSLINC}/bin") + set(OPENSSL_INCDIR "${WITH_OPENSSLINC}/include") + set(OPENSSL_LIBDIR "${WITH_OPENSSLINC}/lib") + # starting with OpenSSL 1.1.0, the Windows crypt32 library is needed for a static link of OpenSSL. + set(OPENSSL_LIBS "crypt32" debug "${OPENSSL_LIBDIR}/dcmtkssl_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkssl_o.lib" debug "${OPENSSL_LIBDIR}/dcmtkcrypto_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkcrypto_o.lib") + set(TEMP_INCLUDES "${CMAKE_REQUIRED_INCLUDES}") + list(APPEND CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCDIR}") + CHECK_CXX_SOURCE_COMPILES("extern \"C\" {\n#include \n}\nint main(){\n#if OPENSSL_VERSION_NUMBER < 0x10001000L\n#error OpenSSL too old\n#endif\n}\n" OPENSSL_VERSION_CHECK) + set(CMAKE_REQUIRED_INCLUDES "${TEMP_INCLUDES}") + if(OPENSSL_VERSION_CHECK) + message(STATUS "Info: DCMTK OPENSSL support will be enabled") + set(WITH_OPENSSL 1) + else() + message(STATUS "Info: DCMTK OPENSSL support will be disabled: DCMTK requires OpenSSL version 1.0.1 or newer") + set(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) + set(WITH_OPENSSL "") + endif() + else() # turn off library if library path not set + message(STATUS "Warning: OPENSSL support will be disabled because openssl directory was not specified. Correct path and re-enable DCMTK_WITH_OPENSSL.") + set(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) + set(WITH_OPENSSL "") + endif() + endif() + + # zlib support: configure compiler + if(DCMTK_WITH_ZLIB) + if(WITH_ZLIBINC) + set(ZLIB_INCDIR "${WITH_ZLIBINC}/include") + set(ZLIB_LIBDIR "${WITH_ZLIBINC}/lib") + set(ZLIB_LIBS debug "${ZLIB_LIBDIR}/zlib_d.lib" optimized "${ZLIB_LIBDIR}/zlib_o.lib") + message(STATUS "Info: DCMTK ZLIB support will be enabled") + set(WITH_ZLIB 1) + else() # turn off library if library path not set + message(STATUS "Warning: ZLIB support will be disabled because zlib directory was not specified. Correct path and re-enable DCMTK_WITH_ZLIB.") + set(DCMTK_WITH_ZLIB OFF CACHE BOOL "" FORCE) + set(WITH_ZLIB "") + endif() + endif() + + # sndfile support: configure compiler + if(DCMTK_WITH_SNDFILE) + if(WITH_SNDFILEINC) + set(SNDFILE_INCDIR "${WITH_SNDFILEINC}/include") + set(SNDFILE_LIBDIR "${WITH_SNDFILEINC}/lib") + set(SNDFILE_LIBS debug "${SNDFILE_LIBDIR}/libsndfile_d.lib" optimized "${SNDFILE_LIBDIR}/libsndfile_o.lib") + message(STATUS "Info: DCMTK SNDFILE support will be enabled") + set(WITH_SNDFILE 1) + else() # turn off library if library path not set + message(STATUS "Warning: SNDFILE support will be disabled because libsndfile directory was not specified. Correct path and re-enable DCMTK_WITH_SNDFILE.") + set(DCMTK_WITH_SNDFILE OFF CACHE BOOL "" FORCE) + set(WITH_SNDFILE "") + endif() + endif() + + # libiconv support: configure compiler + if(DCMTK_WITH_ICONV) + if(WITH_LIBICONVINC) + set(LIBICONV_INCDIR "${WITH_LIBICONVINC}/include") + set(LIBICONV_LIBDIR "${WITH_LIBICONVINC}/lib") + set(LIBICONV_LIBS debug "${LIBICONV_LIBDIR}/libiconv_d.lib" optimized "${LIBICONV_LIBDIR}/libiconv_o.lib") + message(STATUS "Info: DCMTK ICONV support will be enabled") + set(WITH_LIBICONV 1) + else() # turn off library if library path not set + message(STATUS "Warning: ICONV support will be disabled because libiconv directory was not specified. Correct path and re-enable DCMTK_WITH_ICONV.") + set(DCMTK_WITH_ICONV OFF CACHE BOOL "" FORCE) + set(WITH_LIBICONV "") + endif() + endif() + + # OpenJPEG support: configure compiler + if(DCMTK_WITH_OPENJPEG) + if(WITH_OPENJPEGINC) + # Unfortunately, OpenJPEG uses a version number in the include path. This needs special handling. + file(GLOB OPENJPEG2_DIR "${WITH_OPENJPEGINC}/include/openjpeg*") + find_path(WITH_OPENJPEGINC1 "openjpeg.h" "${OPENJPEG2_DIR}" NO_DEFAULT_PATH) + if ("${WITH_OPENJPEGINC1}" STREQUAL "WITH_OPENJPEGINC1-NOTFOUND") + message(STATUS "Info: DCMTK OpenJPEG support will be disabled because the header files were not found.") + set(DCMTK_WITH_OPENJPEG OFF CACHE BOOL "" FORCE) + set(WITH_OPENJPEG "") + else() + set(OPENJPEG_INCDIR "${WITH_OPENJPEGINC1}") + set(OPENJPEG_LIBDIR "${WITH_OPENJPEGINC}/lib") + set(OPENJPEG_LIBS debug "${OPENJPEG_LIBDIR}/openjp2_d.lib" optimized "${OPENJPEG_LIBDIR}/openjp2_o.lib") + message(STATUS "Info: DCMTK OpenJPEG support will be enabled") + set(WITH_OPENJPEG 1) + endif() + else() # turn off library if library path not set + message(STATUS "Warning: OpenJPEG support will be disabled because openjpeg directory was not specified. Correct path and re-enable DCMTK_WITH_OPENJPEG.") + set(DCMTK_WITH_OPENJPEG OFF CACHE BOOL "" FORCE) + set(WITH_OPENJPEG "") + endif() + endif() +endif() if(NOT DEFINED DCMTK_WITH_STDLIBC_ICONV) include(CheckCXXSourceCompiles) diff --git a/CMake/DCMTKConfig.cmake.in b/CMake/DCMTKConfig.cmake.in index c344bf28..41905036 100644 --- a/CMake/DCMTKConfig.cmake.in +++ b/CMake/DCMTKConfig.cmake.in @@ -36,17 +36,67 @@ set(DCMTK_ENABLE_PRIVATE_TAGS @DCMTK_ENABLE_PRIVATE_TAGS@) set(DCMTK_ENABLE_CXX11 @DCMTK_ENABLE_CXX11@) set(DCMTK_CXX11_FLAGS @DCMTK_CXX11_FLAGS@) set(DCMTK_ENABLE_STL @DCMTK_ENABLE_STL@) +set(DCMTK_ENABLE_STL_ALGORITHM @DCMTK_ENABLE_STL_ALGORITHM@) +set(DCMTK_ENABLE_STL_LIMITS @DCMTK_ENABLE_STL_LIMITS@) +set(DCMTK_ENABLE_STL_LIST @DCMTK_ENABLE_STL_LIST@) +set(DCMTK_ENABLE_STL_MAP @DCMTK_ENABLE_STL_MAP@) +set(DCMTK_ENABLE_STL_MEMORY @DCMTK_ENABLE_STL_MEMORY@) +set(DCMTK_ENABLE_STL_STACK @DCMTK_ENABLE_STL_STACK@) +set(DCMTK_ENABLE_STL_STRING @DCMTK_ENABLE_STL_STRING@) +set(DCMTK_ENABLE_STL_SYSTEM_ERROR @DCMTK_ENABLE_STL_SYSTEM_ERROR@) +set(DCMTK_ENABLE_STL_TUPLE @DCMTK_ENABLE_STL_TUPLE@) +set(DCMTK_ENABLE_STL_TYPE_TRAITS @DCMTK_ENABLE_STL_TYPE_TRAITS@) +set(DCMTK_ENABLE_STL_VECTOR @DCMTK_ENABLE_STL_VECTOR@) -# DCMTK shared libraries +set(DCMTK_FORCE_FPIC_ON_UNIX @DCMTK_FORCE_FPIC_ON_UNIX@) + +# DCMTK documentation +set(DCMTK_GENERATE_DOXYGEN_TAGFILE @DCMTK_GENERATE_DOXYGEN_TAGFILE@) + +# DCMTK shared libraries and build model +set(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS @DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS@) +set(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL @DCMTK_COMPILE_WIN32_MULTITHREADED_DLL@) set(DCMTK_SHARED_LIBRARIES @BUILD_SHARED_LIBS@) set(DCMTK_SINGLE_SHARED_LIBRARY @BUILD_SINGLE_SHARED_LIBRARY@) # DCMTK additional options +set(DCMTK_BUILD_APPS @BUILD_APPS@) set(DCMTK_WITH_THREADS @DCMTK_WITH_THREADS@) -set(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS @DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS@) set(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS @DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS@) set(DCMTK_WIDE_CHAR_MAIN_FUNCTION @DCMTK_WIDE_CHAR_MAIN_FUNCTION@) set(DCMTK_ENABLE_LFS @DCMTK_ENABLE_LFS@) +set(DCMTK_ENABLE_CHARSET_CONVERSION @DCMTK_ENABLE_CHARSET_CONVERSION@) + + +# CMake builtins +set(DCMTK_CMAKE_BUILD_TYPE @CMAKE_BUILD_TYPE@) +set(DCMTK_CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@") + +set(DCMTK_CMAKE_CXX_FLAGS @CMAKE_CXX_FLAGS@) +set(DCMTK_CMAKE_CXX_FLAGS_DEBUG @CMAKE_CXX_FLAGS_DEBUG@) +set(DCMTK_CMAKE_CXX_FLAGS_RELEASE @CMAKE_CXX_FLAGS_RELEASE@) +set(DCMTK_CMAKE_CXX_FLAGS_MINSIZEREL @CMAKE_CXX_FLAGS_MINSIZEREL@) +set(DCMTK_CMAKE_CXX_FLAGS_RELWITHDEBINFO @CMAKE_CXX_FLAGS_RELWITHDEBINFO@) + +set(DCMTK_CMAKE_C_FLAGS_DEBUG @CMAKE_C_FLAGS_DEBUG@) +set(DCMTK_CMAKE_C_FLAGS_RELEASE @CMAKE_C_FLAGS_RELEASE@) +set(DCMTK_CMAKE_C_FLAGS_MINSIZEREL @CMAKE_C_FLAGS_MINSIZEREL@) +set(DCMTK_CMAKE_C_FLAGS_RELWITHDEBINFO @CMAKE_C_FLAGS_RELWITHDEBINFO@) + +set(DCMTK_CMAKE_EXE_LINKER_FLAGS @CMAKE_EXE_LINKER_FLAGS_DEBUG@) +set(DCMTK_CMAKE_EXE_LINKER_FLAGS_DEBUG @CMAKE_EXE_LINKER_FLAGS_DEBUG@) +set(DCMTK_CMAKE_EXE_LINKER_FLAGS_RELEASE @CMAKE_EXE_LINKER_FLAGS_RELEASE@) +set(DCMTK_CMAKE_EXE_LINKER_FLAGS_MINSIZEREL @CMAKE_EXE_LINKER_FLAGS_MINSIZEREL@) +set(DCMTK_CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO @CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO@) + +set(DCMTK_CMAKE_INSTALL_BINDIR @CMAKE_INSTALL_BINDIR@) +set(DCMTK_CMAKE_INSTALL_SYSCONFDIR @CMAKE_INSTALL_SYSCONFDIR@) +set(DCMTK_CMAKE_INSTALL_INCLUDEDIR @CMAKE_INSTALL_INCLUDEDIR@) +set(DCMTK_CMAKE_INSTALL_LIBDIR @CMAKE_INSTALL_LIBDIR@) +set(DCMTK_CMAKE_INSTALL_DATAROOTDIR @CMAKE_INSTALL_DATAROOTDIR@) + +set(DCMTK_CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") + SET_AND_CHECK(DCMTK_TARGETS "@PACKAGE_DCMTK_CMKDIR_CONFIG@/DCMTKTargets.cmake") diff --git a/CMake/GenerateDCMTKConfigure.cmake b/CMake/GenerateDCMTKConfigure.cmake index b067355e..5f2ef72b 100644 --- a/CMake/GenerateDCMTKConfigure.cmake +++ b/CMake/GenerateDCMTKConfigure.cmake @@ -777,17 +777,6 @@ if(NOT DEFINED C_CHAR_UNSIGNED) endif() endif() -DCMTK_TRY_COMPILE(HAVE_CXX_BOOL "C++ type bool exists" - "// Minimal test for existence of 'bool' type. -void TestBool(bool) {} - -int main() -{ - TestBool(false); - TestBool(true); - return 0; -}") - # Check for thread type if(HAVE_WINDOWS_H) set(HAVE_INT_TYPE_PTHREAD_T 1) diff --git a/CMake/dcmtkPrepare.cmake b/CMake/dcmtkPrepare.cmake index 514803a4..23a9278c 100644 --- a/CMake/dcmtkPrepare.cmake +++ b/CMake/dcmtkPrepare.cmake @@ -8,8 +8,8 @@ endif() set(DCMTK_CONFIGURATION_DONE true) # Latest CMake version tested -if(CMAKE_BACKWARDS_COMPATIBILITY GREATER 3.15.3) - set(CMAKE_BACKWARDS_COMPATIBILITY 3.15.3 CACHE STRING "Latest version of CMake when this project was released." FORCE) +if(CMAKE_BACKWARDS_COMPATIBILITY GREATER 3.18.4) + set(CMAKE_BACKWARDS_COMPATIBILITY 3.18.4 CACHE STRING "Latest version of CMake when this project was released." FORCE) endif() # CMAKE_BUILD_TYPE is set to value "Release" if none is specified by the @@ -38,14 +38,14 @@ endif() # a development snapshot and an even number indicates an official release.) set(DCMTK_MAJOR_VERSION 3) set(DCMTK_MINOR_VERSION 6) -set(DCMTK_BUILD_VERSION 5) +set(DCMTK_BUILD_VERSION 6) # The ABI is not guaranteed to be stable between different snapshots/releases, # so this particular version number is increased for each snapshot or release. -set(DCMTK_ABI_VERSION 15) +set(DCMTK_ABI_VERSION 16) # Package "release" settings (some are currently unused and, therefore, disabled) set(DCMTK_PACKAGE_NAME "dcmtk") -set(DCMTK_PACKAGE_DATE "2019-10-28") +set(DCMTK_PACKAGE_DATE "2021-01-14") set(DCMTK_PACKAGE_VERSION "${DCMTK_MAJOR_VERSION}.${DCMTK_MINOR_VERSION}.${DCMTK_BUILD_VERSION}") set(DCMTK_PACKAGE_VERSION_NUMBER ${DCMTK_MAJOR_VERSION}${DCMTK_MINOR_VERSION}${DCMTK_BUILD_VERSION}) set(DCMTK_PACKAGE_VERSION_SUFFIX "") @@ -263,54 +263,17 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") # set project wide flags for compiler and linker if(WIN32) - option(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS "Overwrite compiler flags with DCMTK's WIN32 package default values." ON) + option(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS "Modify the default compiler flags selected by CMake." ON) option(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL "Compile DCMTK using the Multithreaded DLL runtime library." OFF) if (BUILD_SHARED_LIBS) set(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL ON) endif() else() + # these settings play no role on other platforms set(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS OFF) set(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL OFF) endif() -if(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS AND NOT BUILD_SHARED_LIBS) - - # settings for Microsoft Visual Studio - if(CMAKE_GENERATOR MATCHES "Visual Studio .*") - # get Visual Studio Version - string(REGEX REPLACE "Visual Studio ([0-9]+).*" "\\1" VS_VERSION "${CMAKE_GENERATOR}") - # these settings never change even for C or C++ - set(CMAKE_C_FLAGS_DEBUG "/MTd /Z7 /Od") - set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /MT /O2") - set(CMAKE_C_FLAGS_MINSIZEREL "/DNDEBUG /MT /O2") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /MTd /Z7 /Od") - set(CMAKE_CXX_FLAGS_DEBUG "/MTd /Z7 /Od") - set(CMAKE_CXX_FLAGS_RELEASE "/DNDEBUG /MT /O2") - set(CMAKE_CXX_FLAGS_MINSIZEREL "/DNDEBUG /MT /O2") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/DNDEBUG /MTd /Z7 /Od") - # specific settings for the various Visual Studio versions - if(VS_VERSION EQUAL 6) - set(CMAKE_C_FLAGS "/nologo /W3 /GX /Gy /YX") - set(CMAKE_CXX_FLAGS "/nologo /W3 /GX /Gy /YX /Zm500") # /Zm500 increments heap size which is needed on some system to compile templates in dcmimgle - endif() - if(VS_VERSION EQUAL 7) - set(CMAKE_C_FLAGS "/nologo /W3 /Gy") - set(CMAKE_CXX_FLAGS "/nologo /W3 /Gy") - endif() - if(VS_VERSION GREATER 7) - set(CMAKE_C_FLAGS "/nologo /W3 /Gy /EHsc") - set(CMAKE_CXX_FLAGS "/nologo /W3 /Gy /EHsc") - endif() - endif() - - # settings for Borland C++ - if(CMAKE_GENERATOR MATCHES "Borland Makefiles") - # further settings required? not tested for a very long time! - set(CMAKE_STANDARD_LIBRARIES "import32.lib cw32mt.lib") - endif() - -endif() - if(WIN32 AND CMAKE_GENERATOR MATCHES "Visual Studio .*") # Evaluate the DCMTK_COMPILE_WIN32_MULTITHREADED_DLL option and adjust # the runtime library setting (/MT or /MD) accordingly @@ -327,18 +290,20 @@ if(WIN32 AND CMAKE_GENERATOR MATCHES "Visual Studio .*") CMAKE_C_FLAGS_RELWITHDEBINFO ) - if(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL OR BUILD_SHARED_LIBS) - # Convert any /MT or /MTd option to /MD or /MDd - foreach(CompilerFlag ${CompilerFlags}) - string(REPLACE "/MT" "/MD" ${CompilerFlag} "${${CompilerFlag}}") - set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE) - endforeach() - else() - # Convert any /MD or /MDd option to /MT or /MTd - foreach(CompilerFlag ${CompilerFlags}) - string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") - set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE) - endforeach() + if(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS OR BUILD_SHARED_LIBS) + if(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL OR BUILD_SHARED_LIBS) + # Convert any /MT or /MTd option to /MD or /MDd + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MT" "/MD" ${CompilerFlag} "${${CompilerFlag}}") + set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE) + endforeach() + else() + # Convert any /MD or /MDd option to /MT or /MTd + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE) + endforeach() + endif() endif() endif() diff --git a/CMake/osconfig.h.in b/CMake/osconfig.h.in index 3918adc1..c3cf55c5 100644 --- a/CMake/osconfig.h.in +++ b/CMake/osconfig.h.in @@ -104,9 +104,6 @@ /* Define to 1 if you have the `cuserid' function. */ #cmakedefine HAVE_CUSERID @HAVE_CUSERID@ -/* Define if bool is a built-in type */ -#cmakedefine HAVE_CXX_BOOL @HAVE_CXX_BOOL@ - /* Define if volatile is a known keyword */ #define HAVE_CXX_VOLATILE 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index a042e7a5..028e1d17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,24 +18,18 @@ cmake_policy(VERSION "${DCMTK_CMAKE_POLICY_VERSION}") # Declare project project(DCMTK) -# Check the build system -include(CMake/dcmtkPrepare.cmake NO_POLICY_SCOPE) - #----------------------------------------------------------------------------- # General project settings to configure DCMTK build process #----------------------------------------------------------------------------- # Modules to be built - set(DCMTK_MODULES ofstd oflog dcmdata dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr - dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmiod dcmfg dcmseg dcmtract dcmpmap + dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmiod dcmfg + dcmseg dcmtract dcmpmap dcmect CACHE STRING "List of modules that should be built.") -#----------------------------------------------------------------------------- # Include directories -#----------------------------------------------------------------------------- - set(DCMTK_INCLUDE_DIR "${DCMTK_BINARY_DIR}/config/include") foreach(inc ${DCMTK_MODULES}) list(APPEND DCMTK_INCLUDE_DIR "${DCMTK_SOURCE_DIR}/${inc}/include") @@ -43,11 +37,17 @@ endforeach() include_directories(${DCMTK_INCLUDE_DIR}) +#----------------------------------------------------------------------------- +# Check the build system +#----------------------------------------------------------------------------- + +include(CMake/dcmtkPrepare.cmake NO_POLICY_SCOPE) + #----------------------------------------------------------------------------- # Prepare osconfig.h #----------------------------------------------------------------------------- -# add the osconfig.h.in file +# Add the osconfig.h.in file configure_file("${DCMTK_SOURCE_DIR}/CMake/osconfig.h.in" "${DCMTK_BINARY_DIR}/config/include/dcmtk/config/osconfig.h") @@ -100,7 +100,7 @@ install(FILES "${DCMTK_BINARY_DIR}/config/include/dcmtk/config/osconfig.h" COMPONENT include) # Install DCMTK's general documentation files -install(FILES ANNOUNCE CHANGES COPYRIGHT CREDITS FAQ HISTORY VERSION +install(FILES ANNOUNCE COPYRIGHT CREDITS FAQ HISTORY VERSION DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT doc) install(DIRECTORY docs/ DESTINATION "${CMAKE_INSTALL_DOCDIR}" @@ -187,7 +187,7 @@ if(CMAKE_CROSSCOMPILING) "${DCMTK_RUN_CTEST_SCRIPT}" ESCAPE_QUOTES @ONLY ) else() - # nothing to do + # Nothing to do endif() else() string(REPLACE ";" "${ENVIRONMENT_PATH_SEPARATOR}" DCMDICTPATH "${DCMTK_DICOM_DICTIONARIES}") diff --git a/COPYRIGHT b/COPYRIGHT index 13b996d5..6de6e4eb 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -5,7 +5,7 @@ Unless otherwise specified, the DCMTK software package has the following copyright: /* - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2021, OFFIS e.V. * All rights reserved. * * This software and supporting documentation were developed by @@ -48,6 +48,8 @@ Please note that some DCMTK modules, especially those that are not part of the free toolkit, are covered by a separate license which can be found in the COPYRIGHT file in the corresponding module directory. +--------------------------------------------------------------------------- + Some portions of the DCMTK software package are derived from earlier versions of this software with the following copyright, and can be identified by the following copyright notice located in each source file: @@ -99,6 +101,8 @@ identified by the following copyright notice located in each source file: * */ +--------------------------------------------------------------------------- + Some other parts of this software within the dcmtk/dcmnet sub-package related to the DICOM Upper Layer Protocol are derived from software developed for the RSNA'93 DICOM demonstration and kindly made available @@ -138,6 +142,8 @@ source file: * the copyright notice. */ +--------------------------------------------------------------------------- + The dcmjpeg sub-package includes an adapted version of the Independent JPEG Group Toolkit Version 6b, which is contained in dcmjpeg/libijg8, dcmjpeg/libijg12 and dcmjpeg/libijg16. This toolkit is covered by the @@ -181,6 +187,8 @@ Group Toolkit is located in dcmjpeg/docs/ijg_readme.txt. * assumed by the product vendor. */ +--------------------------------------------------------------------------- + The code for the interpolatePixel() image scaling algorithm in module dcmimgle has been derived from code written by Jef Poskanzer for the "Extended Portable Bitmap Toolkit" (pbmplus10dec91) which has the @@ -197,6 +205,8 @@ following copyright: * implied warranty. */ +--------------------------------------------------------------------------- + The color quantization code in module dcmimage (dcmquant and the related classes) has been derived from code written by Jef Poskanzer for the NetPBM toolkit which has the following copyright: @@ -212,6 +222,8 @@ NetPBM toolkit which has the following copyright: * implied warranty. */ +--------------------------------------------------------------------------- + The code for the OFStandard::strlcpy and OFStandard::strlcat helper functions in ofstd/libsrc/ofstd.cc has been derived from the BSD implementation of strlcpy() and strlcat() and which carries the @@ -244,6 +256,8 @@ following copyright notice: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +--------------------------------------------------------------------------- + The code for the OFStandard::atof helper function in ofstd/libsrc/ofstd.cc has been derived from an implementation which carries the following copyright notice: @@ -277,6 +291,8 @@ copyright notice: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +--------------------------------------------------------------------------- + The "Base64" encoder/decoder in ofstd/libsrc/ofstd.cc has been derived from an implementation which carries the following copyright notice: @@ -287,6 +303,8 @@ from an implementation which carries the following copyright notice: * provided the authors copyright notice remains intact. */ +--------------------------------------------------------------------------- + The oflog sub-package is based on the log4cplus library which is covered by the following two copyright notices (for details see oflog/docs/LICENSE): @@ -337,6 +355,8 @@ the following two copyright notices (for details see oflog/docs/LICENSE): // See the License for the specific language governing permissions and // limitations under the License. +--------------------------------------------------------------------------- + The dcmjpls sub-package is based on the CharLS library, which is contained in dcmjpls/libcharls. This toolkit is covered by the following copyright: @@ -372,6 +392,8 @@ in dcmjpls/libcharls. This toolkit is covered by the following copyright: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +--------------------------------------------------------------------------- + The file ofstd/include/dcmtk/ofstd/oftest.h is heavily based on quicktest.h from the quicktest project, which is covered by the following copyright: @@ -431,7 +453,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---- +--------------------------------------------------------------------------- The files ofstd/include/dcmtk/ofstd/ofxml.h and ofstd/libsrc/ofxml.cc are derived from the XMLparser library, which is covered by the following @@ -473,12 +495,14 @@ copyright: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +--------------------------------------------------------------------------- + The dcmrt sub-package is covered by the following copyright: --------------------------------------------------------------------------- Copyright (C) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany -Copyright (C) 2013-2019, J. Riesmeier, Oldenburg, Germany +Copyright (C) 2013-2021, J. Riesmeier, Oldenburg, Germany All rights reserved. Redistribution and use in source and binary forms, with or without @@ -507,11 +531,13 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- + Parts of the dcmsr sub-package are covered by the following copyright: --------------------------------------------------------------------------- -Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany +Copyright (C) 2015-2021, J. Riesmeier, Oldenburg, Germany All rights reserved. Redistribution and use in source and binary forms, with or without @@ -583,6 +609,8 @@ For binary libraries and executables statically linked against these external libraries, the following additional copyright notices / licenses apply: +--------------------------------------------------------------------------- + When compiled with libiconv support: --------------------------------------------------------------------------- diff --git a/CREDITS b/CREDITS index 851b8353..b4a3902f 100644 --- a/CREDITS +++ b/CREDITS @@ -16,6 +16,9 @@ Epilepsieforschung: The Gesellschaft fuer Epilepsieforschung e.V. (Bielefeld, Germany) supported the DCMTK by sponsoring the initial development of the tool "dcmrecv" and the underlying class "DcmStorageSCP". +GE Aviation: GE Aviation supported DCMTK by sponsoring the development of the + dcmect library and basic concatenation support in dcmfg. + ICSMED: From 2006 to 2012, the work on the DCMTK was supported by employees of the ICSMED AG (Oldenburg, Germany), a spin-off from the OFFIS institute. @@ -58,4 +61,4 @@ YXLON: The work on the initial version of the DICONDE data dictionary was Please note that this list does not claim to be exhaustive. Just send us an email if you think that you or your company/organization should also be listed. -DCMTK Team, 2017-04-20 +DCMTK Team, 2021-01-14 diff --git a/INSTALL b/INSTALL index 67b396ac..24f317cd 100644 --- a/INSTALL +++ b/INSTALL @@ -1,4 +1,3 @@ -================================== DICOM TOOLKIT (DCMTK) INSTALLATION ================================== @@ -32,21 +31,28 @@ The DCMTK software can be compiled under a native Microsoft Windows environment The current (minor) release successfully compiles on the following operating system / hardware / compiler combinations: - Windows 7 / Intel x86 / Microsoft Visual C++ 2008 Express (VS 9) Windows 7 / Intel x86 / Microsoft Visual C++ 2010 Express (VS 10) - Windows 7 / Intel x86 / Microsoft Visual C++ 2012 Express (VS 11) - Windows 7 / Intel x86 / Microsoft Visual C++ 2013 Express (VS 12) Windows 7 / Intel x86 / Microsoft Visual C++ 2015 Community (VS 14) - Windows 7 / Intel x86 / Microsoft Visual C++ 2017 Community (VS 15) - Windows 7 / Intel x86 / MinGW gcc 7.4.0 (i686-w64-mingw32) Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2010 Express (VS 10) - Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2012 Express (VS 11) - Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2013 Express (VS 12) Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2015 Community (VS 14) - Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2017 Community (VS 15) - Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2019 Community (VS 16) - Windows 7 / amd64|x86_64 / MinGW gcc 8.2.1 (x86_64-w64-mingw32) + Windows 10 / Intel x86 / Microsoft Visual C++ 2008 Express (VS 9) + Windows 10 / Intel x86 / Microsoft Visual C++ 2010 Express (VS 10) + Windows 10 / Intel x86 / Microsoft Visual C++ 2012 Express (VS 11) + Windows 10 / Intel x86 / Microsoft Visual C++ 2013 Express (VS 12) + Windows 10 / Intel x86 / Microsoft Visual C++ 2015 Community (VS 14) + Windows 10 / Intel x86 / Microsoft Visual C++ 2017 Community (VS 15) + Windows 10 / Intel x86 / Microsoft Visual C++ 2019 Community (VS 16) + Windows 10 / Intel x86 / MinGW gcc 9.2.0 (i686-w64-mingw32) + Windows 10 / Intel x86 / MinGW gcc 10.2.0 (i686-w64-mingw32) + Windows 10 / Intel x86 / MinGW Clang 10.0.1 (i686-w64-mingw32) + Windows 10 / amd64|x86_64 / Microsoft Visual C++ 2012 Express (VS 11) + Windows 10 / amd64|x86_64 / Microsoft Visual C++ 2013 Express (VS 12) + Windows 10 / amd64|x86_64 / Microsoft Visual C++ 2015 Community (VS 14) + Windows 10 / amd64|x86_64 / Microsoft Visual C++ 2017 Community (VS 15) Windows 10 / amd64|x86_64 / Microsoft Visual C++ 2019 Community (VS 16) + Windows 10 / amd64|x86_64 / MinGW gcc 9.2.0 (x86_64-w64-mingw32) + Windows 10 / amd64|x86_64 / MinGW gcc 10.2.0 (x86_64-w64-mingw32) + Windows 10 / amd64|x86_64 / MinGW Clang 10.0.1 (x86_64-w64-mingw32) Unix (or lookalikes) -------------------- @@ -55,26 +61,34 @@ The current DCMTK software release successfully compiles on the following operating system / hardware / compiler combinations using the instructions given below: - FreeBSD 12.0 / amd64|x86_64 / Clang 6.0.1 + FreeBSD 12.2 / amd64|x86_64 / Clang 10.0.1 Linux 3.2.0 / amd64|x86_64 / GNU gcc 4.4.7 (Debian 7.11) - Linux 3.10.0 / amd64|x86_64 / Clang 3.4.2 (CentOS 7.7) - Linux 3.10.0 / amd64|x86_64 / GNU gcc 4.8.5 (CentOS 7.7) + Linux 3.10.0 / amd64|x86_64 / Clang 3.4.2 (CentOS 7.9) + Linux 3.10.0 / amd64|x86_64 / GNU gcc 4.8.5 (CentOS 7.9) Linux 3.13.0 / amd64|x86_64 / Clang 3.9.1 (Linux Mint 17.3) Linux 3.13.0 / amd64|x86_64 / GNU gcc 4.8.5 (Linux Mint 17.3) Linux 3.13.0 / amd64|x86_64 / GNU gcc 5.5.0 (Linux Mint 17.3) Linux 3.13.0 / amd64|x86_64 / GNU gcc 6.5.0 (Linux Mint 17.3) - Linux 3.13.0 / amd64|x86_64 / GNU gcc 8.3.0 (Linux Mint 17.3) + Linux 3.13.0 / amd64|x86_64 / GNU gcc 7.5.0 (Linux Mint 17.3) + Linux 3.13.0 / amd64|x86_64 / GNU gcc 8.4.0 (Linux Mint 17.3) Linux 4.19.0 / Intel x86 / Clang 7.0.1 (Debian 10) Linux 4.19.0 / Intel x86 / GNU gcc 8.3.0 (Debian 10) Linux 4.19.0 / amd64|x86_64 / Clang 7.0.1 (Debian 10) Linux 4.19.0 / amd64|x86_64 / GNU gcc 8.3.0 (Debian 10) - Linux 5.0.0 / amd64|x86_64 / gcc 8.3.0 (Ubuntu Linux) - Linux 5.3.7 / amd64|x86_64 / Clang 9.0.0 (Arch Linux) - Linux 5.3.7 / amd64|x86_64 / GNU gcc 9.2.0 (Arch Linux) + Linux 4.19.41 / amd64|x86_64 / GNU 8.3.0 (Alpine 3.9.4 with musl libc) + Linux 5.4.0 / amd64|x86_64 / Clang 9.0.1 (Ubuntu 20.04) + Linux 5.4.0 / amd64|x86_64 / Clang 10.0.0 (Ubuntu 20.04) + Linux 5.4.0 / amd64|x86_64 / GNU gcc 9.3.0 (Ubuntu 20.04) + Linux 5.4.0 / amd64|x86_64 / GNU gcc 10.2.0 (Ubuntu 20.04) + Linux 5.8.0 / amd64|x86_64 / GNU gcc 10.2.0 (Ubuntu 20.10) + Linux 5.8.0 / amd64|x86_64 / Clang 11.0.0 (Ubuntu 20.10) MacOS X 10.15 / amd64|x86_64 / Apple Clang 11.0.0 MacOS X 10.15 / amd64|x86_64 / GNU gcc 9.2.0 - OpenBSD 6.5 / amd64|x86_64 / Clang 7.0.1 - OpenBSD 6.5 / amd64|x86_64 / GNU gcc 4.2.1 + NetBSD 9.0 / amd64|x86_64 / Clang 9.0.1 + NetBSD 9.0 / amd64|x86_64 / GNU gcc 7.4.0 + OpenBSD 6.8 / amd64|x86_64 / Clang 10.0.1 + OpenBSD 6.8 / amd64|x86_64 / GNU gcc 4.2.1 + OpenBSD 6.8 / amd64|x86_64 / GNU gcc 8.4.0 OpenIndiana / Intel x86 / GNU gcc 8.3.0 (OpenIndiana 2019.04) Solaris 11.3 / Intel x86 / GNU gcc 4.8.2 Solaris 11.3 / Intel x86 / SunPro CC 5.14 (Oracle Developer Studio 12.5) @@ -86,7 +100,7 @@ Cross Compiling The current DCMTK release can be cross-compiled targeting the following platforms: - Android / arm64 / GNU gcc 6.3.0 (API 24, ABI arm64-v8a) + Android / arm64 / GNU gcc 8.3.0 (API 24, ABI arm64-v8a) Cross compiling support with running configuration and unit tests is currently only provided using CMake and requires the use of the Android emulator or Wine @@ -97,6 +111,19 @@ that is being regularly tested. Other Platforms --------------- +The previous minor release DCMTK 3.6.5 was also tested on the following +platforms that may still work, but were not tested again for this minor release: + + Android / arm64 / GNU gcc 6.3.0 (API 24, ABI arm64-v8a) + FreeBSD 12.0 / amd64|x86_64 / Clang 6.0.1 + Linux 5.0.0 / amd64|x86_64 / gcc 8.3.0 (Ubuntu Linux) + Linux 5.3.7 / amd64|x86_64 / Clang 9.0.0 (Arch Linux) + Linux 5.3.7 / amd64|x86_64 / GNU gcc 9.2.0 (Arch Linux) + OpenBSD 6.5 / amd64|x86_64 / Clang 7.0.1 + OpenBSD 6.5 / amd64|x86_64 / GNU gcc 4.2.1 + Windows 10 / Intel x86 / MinGW gcc 7.4.0 (i686-w64-mingw32) + Windows 10 / amd64|x86_64 / MinGW gcc 8.2.1 (x86_64-w64-mingw32) + The previous minor release DCMTK 3.6.4 was also tested on the following platforms that may still work, but were not tested again for this minor release: @@ -162,12 +189,19 @@ using the Transport Layer Security (TLS) protocol as defined in DICOM part 15. DCMTK relies on the OpenSSL toolkit (www.openssl.org) for the underlying cryptographic routines and the TLS protocol implementation. -This release of DCMTK requires OpenSSL release 1.0.1 or newer, since older -versions do not support the TLS 1.2 protocol required by the more recent -DICOM security profiles. We recommend the use of OpenSSL 1.0.2 or newer, -however, since some optional functions recommended by RFC 7525 / BCP 195 -are only available starting with this OpenSSL release. Furthermore, users -should make care that the most recent OpenSSL patch level is applied. +This release of DCMTK requires OpenSSL release 1.0.1 or newer. We recommend +the use of OpenSSL 1.0.2 or newer, however, since some optional functions +recommended by RFC 7525 / BCP 195 are only available starting with this +OpenSSL release. Furthermore, users should make care that the most recent +OpenSSL patch level is applied. This release of DCMTK is known to compile with +the OpenSSL releases 1.0.1 to 1.1.1i. + +Note: DCMTK 3.6.6 is explicitly NOT approved for use with the upcoming +OpenSSL 3.0.0 library, which is currently in "alpha" status. OpenSSL 3.0 +will NOT work correctly with the dcmsign module, as it requires some additional +code to load the RIPEMD160 routines, which have been moved to the so-called +"legacy provider" that is not active by default; the required modifications +will be included in the next DCMTK release. When using CMake, if support for security enhancements is desired, a compiled version of the OpenSSL libraries and include files must be available during @@ -196,7 +230,7 @@ LIBTIFF SUPPORT Starting with release 3.5.1, DCMTK supports the conversion of DICOM images to TIFF. DCMTK relies on the libtiff toolkit (www.libtiff.org) for this purpose. This release of DCMTK is known to compile with the libtiff releases 3.8.2 to -4.10.0, although other releases may work as well. However, libtiff releases +4.1.0, although other releases may work as well. However, libtiff releases prior to version 3.7.0 will not work since the TIFFCleanup() function was not yet available. On Windows, libtiff 3.7.4 or higher is required due to incompatible API changes in libtiff. @@ -224,7 +258,7 @@ LIBXML2 SUPPORT Starting with release 3.5.3, DCMTK supports the conversion of XML documents to DICOM files. DCMTK relies on the libxml2 toolkit (www.libxml.org) for this purpose. This release of DCMTK is known to compile with the libxml2 releases -2.9.4 to 2.9.9, although other releases may work as well. +2.9.4 to 2.9.10, although other releases may work as well. When using CMake, if support for XML import is desired, a compiled version of the libxml2 (and possibly iconv) libraries and include files must be available @@ -288,8 +322,8 @@ ICU SUPPORT DCMTK supports the International Components for Unicode (ICU) library as an alternative to the above mentioned libiconv. This release of DCMTK is known to -compile with the ICU releases 59.1 to 65.1, although other releases may work as -well. +compile with the ICU releases 59.1 to 68.1.0, although other releases may work +as well. The ICU may be easier to integrate on some more modern Linux distributions (e.g. Arch Linux) and Windows than the libiconv but (due to the way it is @@ -363,13 +397,13 @@ respectively: use "--enable-stl-", "--disable-stl-" and/or SUPPORT FOR MODERN C++ STANDARDS ================================ -DCMTK can be configured to use several features of modern C++ standards, eg. -(e.g. C++11 move semantics, variadic templates and the like) instead of its own +DCMTK can be configured to use several features of modern C++ standards (e.g. +C++11 move semantics, variadic templates and the like) instead of its own workarounds and fallback implementations. This can be achieved using CMake's variables "CMAKE_CXX_STANDARD" and "CMAKE_CXX_STANDARD_REQUIRED". The previous mechanism only handled C++11 and is available on old versions of -CMake (versions prior 3.1.3): set "DCMTK_ENABLE_CXX11" to "ON". For Autoconf, -use the "--enable-cxx11" argument. Both the "DCMTK_ENABLE_CXX11" variable and +CMake (versions prior 3.1.3): set "DCMTK_ENABLE_CXX11" to "ON". For Autoconf, +use the "--enable-cxx11" argument. Both the "DCMTK_ENABLE_CXX11" variable and Autoconf support are now deprecated and will be removed in a future release. Enabling e.g. C++11 will change some parts of DCMTK's API, so a C++11 build of @@ -399,8 +433,8 @@ directories. In detail, these "CMakeLists.txt" files will serve as an input to CMake which will generate suitable build files for all of DCMTK's projects from these files. -DCMTK 3.6.5 requires CMake version 2.8.5 or later. We recommend using the -latest stable release of CMake (currently version 3.15.4) since newer versions +DCMTK 3.6.6 requires CMake version 2.8.5 or later. We recommend using the +latest stable release of CMake (currently version 3.19.2) since newer versions of CMake often provide better output in case of errors and are generally easier to use (for example by providing better support for detecting the availability of third party libraries). If possible, use the CMake version your operating @@ -416,7 +450,7 @@ CMake and shared libraries The CMake build system allows for building shared libraries instead of static libraries. On Windows systems, these are dynamic link libraries (.dll). On Unix systems, these are shared objects (.so). To enable this, set the -"BUILD_SHARED_LIB" option to "ON". +"BUILD_SHARED_LIBS" option to "ON". Additionally, it is possible to produce a single shared library for the whole toolkit. This mode is controlled by the "BUILD_SINGLE_SHARED_LIBRARY" option. @@ -484,7 +518,7 @@ CMake, perform the following steps: 1. Go Start -> Programs -> CMake -> "CMake" or "CMake (cmake-gui)" to start the CMake utility through which the configuration can be done. 2. In the entry field "Where is the source code:" enter the directory in which - the DCMTK source code resides, e.g. "C:\dcmtk-3.6.5". + the DCMTK source code resides, e.g. "C:\dcmtk-3.6.6". 3. In the entry field "Where to build the binaries:" enter the directory in which the libraries and binaries are to be built, e.g. "C:\dcmtk-msvc15". 4. In the combobox "Build for:" or "Specify the generator for this project:" @@ -507,11 +541,11 @@ CMake, perform the following steps: libtiff support: set "DCMTK_WITH_TIFF" to "ON" and - set "WITH_LIBTIFFINC" e.g. to "C:\libtiff-4.0.10" + set "WITH_LIBTIFFINC" e.g. to "C:\libtiff-4.1.0" OpenSSL support: set "DCMTK_WITH_OPENSSL" to "ON" and - set "WITH_OPENSSLINC" e.g. to "C:\openssl-1.1.1d" + set "WITH_OPENSSLINC" e.g. to "C:\openssl-1.1.1i" zlib support: set "DCMTK_WITH_ZLIB" to "ON" and @@ -519,7 +553,7 @@ CMake, perform the following steps: libiconv support: set "DCMTK_WITH_ICONV" to "ON" and - set "WITH_LIBICONVINC" e.g. to "C:\libiconv-1.15" + set "WITH_LIBICONVINC" e.g. to "C:\libiconv-1.16" In order to turn the support of a certain external library off, set the value of the corresponding variable ("DCMTK_WITH_XML", "DCMTK_WITH_PNG", @@ -578,6 +612,30 @@ CMake, perform the following steps: for the non-debug multithread runtime (/MT). Precompiled versions of all libraries can be downloaded from https://www.dcmtk.org/dcmtk#lib-win. + In the CMake GUI, there are a few more settings that can be modified + to affect the way DCMTK is compiled. The most important of these are: + + - DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS: By default, DCMTK will compile + using the default compiler options selected by CMake. When this macro + is enabled, these default options are modified based on the value + of the DCMTK_COMPILE_WIN32_MULTITHREADED_DLL setting (see below). + Default: ON. + - DCMTK_COMPILE_WIN32_MULTITHREADED_DLL: Controls the Windows build + model. When this setting is ON, DCMTK compiled with the + "Multithreaded DLL" build model (/MD or /MDd); when the setting is + OFF, DCMTK is compiled with the "Multithreaded" build model + (/MT or /MTd). This setting is ignored unless the + DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS option is ON. + Default: OFF. + - BUILD_SHARED_LIBS: Build the DCMTK libraries as shared libraries. + This setting overrides the value of the options + DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS and + DCMTK_COMPILE_WIN32_MULTITHREADED_DLL, which are both set to ON. + Default: OFF. + - BUILD_SINGLE_SHARED_LIBRARY: Build a single shared library for the + whole toolkit. This setting overrides the value of the option + BUILD_SHARED_LIBS, which is set to ON. Default: OFF. + 7. Go "Configure" a second time. (CMake will adjust the configuration according to the displayed specifications.) 8. Go "OK" or "Generate". (CMake will generate new project files in the @@ -613,10 +671,6 @@ Known limitations of DCMTK on the Windows platform. DCMTK can be configured to use either of the two interfaces. This behavior can be changed in "config/include/dcmtk/config/osconfig.h" in the build directory where the symbol USE_STD_CXX_INCLUDES is declared. -3. DCMTK does not compile when UNICODE or _UNICODE is defined because the - VisualStudio compiler then uses the Unicode version instead of the ANSI - version for all Windows API functions (i.e. type wchar_t instead of char - for all character string parameters and return values). Unix with CMake @@ -638,18 +692,18 @@ https://cmake.org/cmake/help/latest/module/FindZLIB.html . The typical way to build DCMTK on Unix like systems with CMake is as follows (if not using the GUI, in that case look at the description for Windows above): - mkdir dcmtk-3.6.5-build - cd dcmtk-3.6.5-build - cmake ../dcmtk-3.6.5 + mkdir dcmtk-3.6.6-build + cd dcmtk-3.6.6-build + cmake ../dcmtk-3.6.6 make -j8 - make DESTDIR=../dcmtk-3.6.5-install install + make DESTDIR=../dcmtk-3.6.6-install install The above commands assume that the DCMTK source code was extracted to the -current working directory into a folder named dcmtk-3.6.5. DCMTK will be +current working directory into a folder named dcmtk-3.6.6. DCMTK will be configured using CMake with the default options, detecting and including all available support libraries and then compiled using eight CPU cores ('make -j8', adjust as needed). The result will be installed to the directory -"dcmtk-3.6.5-install" next to the source code directory. +"dcmtk-3.6.6-install" next to the source code directory. If you want to modify your build configuration, like enabling or disabling some features of DCMTK (e.g. PNG support), or if you need to modify the @@ -657,10 +711,10 @@ predefined build-variables, you can use the curses based cmake configuration tool 'ccmake'. First, create the initial build setup (system check) and then call ccmake: - mkdir dcmtk-3.6.5-build - cd dcmtk-3.6.5-build - cmake ../dcmtk-3.6.5 - ccmake ../dcmtk-3.6.5 + mkdir dcmtk-3.6.6-build + cd dcmtk-3.6.6-build + cmake ../dcmtk-3.6.6 + ccmake ../dcmtk-3.6.6 Now you can modify the configuration values. Please see the help on the bottom of the screen. When finished, press 'c' to generate a new build configuration, @@ -670,9 +724,9 @@ If you already know the variable names, types and values to set, you can skip the 'ccmake' step above and can call 'cmake' directly with the values set. Example for a build with TCP wrapper disabled: - mkdir dcmtk-3.6.5-build - cd dcmtk-3.6.5-build - cmake -DDCMTK_WITH_WRAP:BOOL=FALSE ../dcmtk-3.6.5 + mkdir dcmtk-3.6.6-build + cd dcmtk-3.6.6-build + cmake -DDCMTK_WITH_WRAP:BOOL=FALSE ../dcmtk-3.6.6 ... The format is NAME:TYPE=VALUE. Use 'ccmake' to find out the variable names and @@ -699,16 +753,16 @@ HTML DOCUMENTATION AND MAN PAGES Most DCMTK modules have been documented with Doxygen (www.doxygen.org), a free source code documentation system similar to Javadoc. Unix users who have Doxygen installed can create a hypertext documentation with "make html" in the -"dcmtk-3.6.5" or "doxygen" directory; Windows and other CMake users should +"dcmtk-3.6.6" or "doxygen" directory; Windows and other CMake users should build the "DOXYGEN" subproject. A project file for Microsoft's HTML Help Workshop can also be generated allowing to create a single CHM file (compressed HTML) from the documentation. Other output formats (e.g. LaTeX) can be enabled by changing the configuration file in the "doxygen" directory. -At the current time, dcmfg, dcmiod, dcmimage, dcmimgle, dcmjpeg, dcmpmap, -dcmpstat, dcmrt, dcmseg, dcmsign, dcmsr, dcmtls, dcmtract, dcmwlm and ofstd are -completely documented; dcmdata, dcmjpls, dcmnet and oflog are almost completely -documented. See FAQ entry: "Where is rest of the documentation?" +At the current time, dcmect, dcmfg, dcmiod, dcmimage, dcmimgle, dcmjpeg, +dcmpmap, dcmpstat, dcmrt, dcmseg, dcmsign, dcmsr, dcmtls, dcmtract, dcmwlm and +ofstd are completely documented; dcmdata, dcmjpls, dcmnet and oflog are almost +completely documented. See FAQ entry: "Where is rest of the documentation?" On Unix platforms, man pages for all command line tools are installed during the "make install" step. In order to use them, just add the directory (e.g. @@ -776,11 +830,11 @@ BUILDING (Unix with Autoconf) ============================= Configuring a DCMTK build with GNU Autoconf has been deprecated with DCMTK -release 3.6.5 and will be removed in future releases. In the current release, +release 3.6.6 and will be removed in future releases. In the current release, the "configure" script in DCMTK's top-level main directory has been removed as the final warning for users of the Autoconf toolchain. If you prefer to build DCMTK with Autoconf, however, this is still possible. Perform the -following steps from the top-level (dcmtk-3.6.5) directory to compile and +following steps from the top-level (dcmtk-3.6.6) directory to compile and install the software: Step 0: @@ -811,15 +865,15 @@ in which OpenSSL is installed. This is usually the directory that has been used as --prefix when compiling and installing OpenSSL. For example, if you wish to enable the security enhancements, and OpenSSL is -installed in "/usr/local/apps/openssl-1.1.1d", then you should start configure +installed in "/usr/local/apps/openssl-1.1.1i", then you should start configure as: ./configure --ignore-deprecation - --with-opensslinc=/usr/local/apps/openssl-1.1.1d + --with-opensslinc=/usr/local/apps/openssl-1.1.1i Configure will assume that the OpenSSL include files are installed in -"/usr/local/apps/openssl-1.1.1d/include" and will expect the library in -"/usr/local/apps/openssl-1.1.1d/lib". Appropriate options will be passed to +"/usr/local/apps/openssl-1.1.1i/include" and will expect the library in +"/usr/local/apps/openssl-1.1.1i/lib". Appropriate options will be passed to the compiler and the linker. Support for zlib, libtiff, libpng, libxml2, libwrap and libiconv can be enabled @@ -828,13 +882,13 @@ path): ./configure --ignore-deprecation --with-libzlibinc=/usr/local/apps/zlib-1.2.11 - --with-libtiffinc=/usr/local/apps/libtiff-4.0.10 + --with-libtiffinc=/usr/local/apps/libtiff-4.1.0 --with-libpnginc=/usr/local/apps/libpng-1.6.37 - --with-libxmlinc=/usr/local/apps/libxml2-2.9.9 + --with-libxmlinc=/usr/local/apps/libxml2-2.9.10 --with-libwrapinc=/usr/local/apps/tcp_wrappers-7.6 - --with-libiconvinc=/usr/local/apps/libiconv-1.15 + --with-libiconvinc=/usr/local/apps/libiconv-1.16 - --with-libicuinc=/usr/local/apps/icu-65.1 + --with-libicuinc=/usr/local/apps/icu-68.1.0 Different configure options can be combined in any order. configure --help will print a list of all existing configure options. configure --help=short @@ -934,4 +988,4 @@ Have fun. M. Eichelberg, J. Riesmeier, M. Onken, J. Schlamelcher, P. Arizpe Gomez DCMTK Development Team, Oldenburg, Germany. -Last revised: 2019-10-28 (Schlamelcher) +Last revised: 2021-01-14 (Onken) diff --git a/Makefile b/Makefile index 84ee6b0d..eec61324 100644 --- a/Makefile +++ b/Makefile @@ -9,43 +9,43 @@ include $(configdir)/Makefile.def .NOTPARALLEL: -all: config-all ofstd-all oflog-all dcmdata-all dcmiod-all dcmfg-all dcmseg-all dcmimgle-all dcmimage-all dcmjpeg-all dcmjpls-all dcmtls-all dcmnet-all dcmsr-all dcmsign-all dcmwlm-all dcmqrdb-all dcmpstat-all dcmrt-all dcmtract-all dcmpmap-all +all: config-all ofstd-all oflog-all dcmdata-all dcmiod-all dcmfg-all dcmseg-all dcmimgle-all dcmimage-all dcmjpeg-all dcmjpls-all dcmtls-all dcmnet-all dcmsr-all dcmsign-all dcmwlm-all dcmqrdb-all dcmpstat-all dcmrt-all dcmtract-all dcmpmap-all dcmect-all -libsrc-all: ofstd-libsrc-all oflog-libsrc-all dcmdata-libsrc-all dcmiod-libsrc-all dcmfg-libsrc-all dcmseg-libsrc-all dcmimgle-libsrc-all dcmimage-libsrc-all dcmjpeg-libsrc-all dcmjpls-libsrc-all dcmtls-libsrc-all dcmnet-libsrc-all dcmsr-libsrc-all dcmsign-libsrc-all dcmwlm-libsrc-all dcmqrdb-libsrc-all dcmpstat-libsrc-all dcmrt-libsrc-all dcmtract-libsrc-all dcmpmap-libsrc-all +libsrc-all: ofstd-libsrc-all oflog-libsrc-all dcmdata-libsrc-all dcmiod-libsrc-all dcmfg-libsrc-all dcmseg-libsrc-all dcmimgle-libsrc-all dcmimage-libsrc-all dcmjpeg-libsrc-all dcmjpls-libsrc-all dcmtls-libsrc-all dcmnet-libsrc-all dcmsr-libsrc-all dcmsign-libsrc-all dcmwlm-libsrc-all dcmqrdb-libsrc-all dcmpstat-libsrc-all dcmrt-libsrc-all dcmtract-libsrc-all dcmpmap-libsrc-all dcmect-libsrc-all -tests-all: config-tests-all ofstd-tests-all oflog-tests-all dcmdata-tests-all dcmiod-tests-all dcmfg-tests-all dcmseg-tests-all dcmimgle-tests-all dcmimage-tests-all dcmjpeg-tests-all dcmjpls-tests-all dcmtls-tests-all dcmnet-tests-all dcmsr-tests-all dcmsign-tests-all dcmwlm-tests-all dcmqrdb-tests-all dcmpstat-tests-all dcmrt-tests-all dcmtract-tests-all dcmpmap-tests-all +tests-all: config-tests-all ofstd-tests-all oflog-tests-all dcmdata-tests-all dcmiod-tests-all dcmfg-tests-all dcmseg-tests-all dcmimgle-tests-all dcmimage-tests-all dcmjpeg-tests-all dcmjpls-tests-all dcmtls-tests-all dcmnet-tests-all dcmsr-tests-all dcmsign-tests-all dcmwlm-tests-all dcmqrdb-tests-all dcmpstat-tests-all dcmrt-tests-all dcmtract-tests-all dcmpmap-tests-all dcmect-tests-all -install: config-install ofstd-install oflog-install dcmdata-install dcmiod-install dcmfg-install dcmseg-install dcmimgle-install dcmimage-install dcmjpeg-install dcmjpls-install dcmtls-install dcmnet-install dcmsr-install dcmsign-install dcmwlm-install dcmqrdb-install dcmpstat-install dcmrt-install dcmtract-install dcmpmap-install dcmtk-install-doc install-man +install: config-install ofstd-install oflog-install dcmdata-install dcmiod-install dcmfg-install dcmseg-install dcmimgle-install dcmimage-install dcmjpeg-install dcmjpls-install dcmtls-install dcmnet-install dcmsr-install dcmsign-install dcmwlm-install dcmqrdb-install dcmpstat-install dcmrt-install dcmtract-install dcmpmap-install dcmect-install dcmtk-install-doc install-man install-all: install install-lib install-html -install-bin: config-install-bin ofstd-install-bin oflog-install-bin dcmdata-install-bin dcmiod-install-bin dcmfg-install-bin dcmseg-install-bin dcmimgle-install-bin dcmimage-install-bin dcmjpeg-install-bin dcmjpls-install-bin dcmtls-install-bin dcmnet-install-bin dcmsr-install-bin dcmsign-install-bin dcmwlm-install-bin dcmqrdb-install-bin dcmpstat-install-bin dcmrt-install-bin dcmtract-install-bin dcmpmap-install-bin +install-bin: config-install-bin ofstd-install-bin oflog-install-bin dcmdata-install-bin dcmiod-install-bin dcmfg-install-bin dcmseg-install-bin dcmimgle-install-bin dcmimage-install-bin dcmjpeg-install-bin dcmjpls-install-bin dcmtls-install-bin dcmnet-install-bin dcmsr-install-bin dcmsign-install-bin dcmwlm-install-bin dcmqrdb-install-bin dcmpstat-install-bin dcmrt-install-bin dcmtract-install-bin dcmpmap-install-bin dcmect-install-bin -install-doc: config-install-doc ofstd-install-doc oflog-install-doc dcmdata-install-doc dcmiod-install-doc dcmfg-install-doc dcmseg-install-doc dcmimgle-install-doc dcmimage-install-doc dcmjpeg-install-doc dcmjpls-install-doc dcmtls-install-doc dcmnet-install-doc dcmsr-install-doc dcmsign-install-doc dcmwlm-install-doc dcmqrdb-install-doc dcmpstat-install-doc dcmrt-install-doc dcmtract-install-doc dcmpmap-install-doc +install-doc: config-install-doc ofstd-install-doc oflog-install-doc dcmdata-install-doc dcmiod-install-doc dcmfg-install-doc dcmseg-install-doc dcmimgle-install-doc dcmimage-install-doc dcmjpeg-install-doc dcmjpls-install-doc dcmtls-install-doc dcmnet-install-doc dcmsr-install-doc dcmsign-install-doc dcmwlm-install-doc dcmqrdb-install-doc dcmpstat-install-doc dcmrt-install-doc dcmtract-install-doc dcmpmap-install-doc dcmect-install-doc -install-data: config-install-data ofstd-install-data oflog-install-data dcmdata-install-data dcmiod-install-data dcmfg-install-data dcmseg-install-data dcmimgle-install-data dcmimage-install-data dcmjpeg-install-data dcmjpls-install-data dcmtls-install-data dcmnet-install-data dcmsr-install-data dcmsign-install-data dcmwlm-install-data dcmqrdb-install-data dcmpstat-install-data dcmrt-install-data dcmtract-install-data dcmpmap-install-data +install-data: config-install-data ofstd-install-data oflog-install-data dcmdata-install-data dcmiod-install-data dcmfg-install-data dcmseg-install-data dcmimgle-install-data dcmimage-install-data dcmjpeg-install-data dcmjpls-install-data dcmtls-install-data dcmnet-install-data dcmsr-install-data dcmsign-install-data dcmwlm-install-data dcmqrdb-install-data dcmpstat-install-data dcmrt-install-data dcmtract-install-data dcmpmap-install-data dcmect-install-data -install-etc: config-install-etc ofstd-install-etc oflog-install-etc dcmdata-install-etc dcmiod-install-etc dcmfg-install-etc dcmseg-install-etc dcmimgle-install-etc dcmimage-install-etc dcmjpeg-install-etc dcmjpls-install-etc dcmtls-install-etc dcmnet-install-etc dcmsr-install-etc dcmsign-install-etc dcmwlm-install-etc dcmqrdb-install-etc dcmpstat-install-etc dcmrt-install-etc dcmtract-install-etc dcmpmap-install-etc +install-etc: config-install-etc ofstd-install-etc oflog-install-etc dcmdata-install-etc dcmiod-install-etc dcmfg-install-etc dcmseg-install-etc dcmimgle-install-etc dcmimage-install-etc dcmjpeg-install-etc dcmjpls-install-etc dcmtls-install-etc dcmnet-install-etc dcmsr-install-etc dcmsign-install-etc dcmwlm-install-etc dcmqrdb-install-etc dcmpstat-install-etc dcmrt-install-etc dcmtract-install-etc dcmpmap-install-etc dcmect-install-etc -install-lib: config-install-lib ofstd-install-lib oflog-install-lib dcmdata-install-lib dcmiod-install-lib dcmfg-install-lib dcmseg-install-lib dcmimgle-install-lib dcmimage-install-lib dcmjpeg-install-lib dcmjpls-install-lib dcmtls-install-lib dcmnet-install-lib dcmsr-install-lib dcmsign-install-lib dcmwlm-install-lib dcmqrdb-install-lib dcmpstat-install-lib dcmrt-install-lib dcmtract-install-lib dcmpmap-install-lib +install-lib: config-install-lib ofstd-install-lib oflog-install-lib dcmdata-install-lib dcmiod-install-lib dcmfg-install-lib dcmseg-install-lib dcmimgle-install-lib dcmimage-install-lib dcmjpeg-install-lib dcmjpls-install-lib dcmtls-install-lib dcmnet-install-lib dcmsr-install-lib dcmsign-install-lib dcmwlm-install-lib dcmqrdb-install-lib dcmpstat-install-lib dcmrt-install-lib dcmtract-install-lib dcmpmap-install-lib dcmect-install-lib -install-include: config-install-include ofstd-install-include oflog-install-include dcmdata-install-include dcmiod-install-include dcmfg-install-include dcmseg-install-include dcmimgle-install-include dcmimage-install-include dcmjpeg-install-include dcmjpls-install-include dcmtls-install-include dcmnet-install-include dcmsr-install-include dcmsign-install-include dcmwlm-install-include dcmqrdb-install-include dcmpstat-install-include dcmrt-install-include dcmtract-install-include dcmpmap-install-include +install-include: config-install-include ofstd-install-include oflog-install-include dcmdata-install-include dcmiod-install-include dcmfg-install-include dcmseg-install-include dcmimgle-install-include dcmimage-install-include dcmjpeg-install-include dcmjpls-install-include dcmtls-install-include dcmnet-install-include dcmsr-install-include dcmsign-install-include dcmwlm-install-include dcmqrdb-install-include dcmpstat-install-include dcmrt-install-include dcmtract-install-include dcmpmap-install-include dcmect-install-include -install-support: config-install-support ofstd-install-support oflog-install-support dcmdata-install-support dcmiod-install-support dcmfg-install-support dcmseg-install-support dcmimgle-install-support dcmimage-install-support dcmjpeg-install-support dcmjpls-install-support dcmtls-install-support dcmnet-install-support dcmsr-install-support dcmsign-install-support dcmwlm-install-support dcmqrdb-install-support dcmpstat-install-support dcmrt-install-support dcmtract-install-support dcmpmap-install-support +install-support: config-install-support ofstd-install-support oflog-install-support dcmdata-install-support dcmiod-install-support dcmfg-install-support dcmseg-install-support dcmimgle-install-support dcmimage-install-support dcmjpeg-install-support dcmjpls-install-support dcmtls-install-support dcmnet-install-support dcmsr-install-support dcmsign-install-support dcmwlm-install-support dcmqrdb-install-support dcmpstat-install-support dcmrt-install-support dcmtract-install-support dcmpmap-install-support dcmect-install-support check: tests-all $(MAKE) -s check-nosilent -check-nosilent: config-check ofstd-check oflog-check dcmdata-check dcmiod-check dcmfg-check dcmseg-check dcmimgle-check dcmimage-check dcmjpeg-check dcmjpls-check dcmtls-check dcmnet-check dcmsr-check dcmsign-check dcmwlm-check dcmqrdb-check dcmpstat-check dcmrt-check dcmtract-check dcmpmap-check +check-nosilent: config-check ofstd-check oflog-check dcmdata-check dcmiod-check dcmfg-check dcmseg-check dcmimgle-check dcmimage-check dcmjpeg-check dcmjpls-check dcmtls-check dcmnet-check dcmsr-check dcmsign-check dcmwlm-check dcmqrdb-check dcmpstat-check dcmrt-check dcmtract-check dcmpmap-check dcmect-check check-exhaustive: tests-all $(MAKE) -s check-nosilent-exhaustive -check-nosilent-exhaustive: config-check-exhaustive ofstd-check-exhaustive oflog-check-exhaustive dcmdata-check-exhaustive dcmiod-check-exhaustive dcmfg-check-exhaustive dcmseg-check-exhaustive dcmimgle-check-exhaustive dcmimage-check-exhaustive dcmjpeg-check-exhaustive dcmjpls-check-exhaustive dcmtls-check-exhaustive dcmnet-check-exhaustive dcmsr-check-exhaustive dcmsign-check-exhaustive dcmwlm-check-exhaustive dcmqrdb-check-exhaustive dcmpstat-check-exhaustive dcmrt-check-exhaustive dcmtract-check-exhaustive dcmpmap-check-exhaustive +check-nosilent-exhaustive: config-check-exhaustive ofstd-check-exhaustive oflog-check-exhaustive dcmdata-check-exhaustive dcmiod-check-exhaustive dcmfg-check-exhaustive dcmseg-check-exhaustive dcmimgle-check-exhaustive dcmimage-check-exhaustive dcmjpeg-check-exhaustive dcmjpls-check-exhaustive dcmtls-check-exhaustive dcmnet-check-exhaustive dcmsr-check-exhaustive dcmsign-check-exhaustive dcmwlm-check-exhaustive dcmqrdb-check-exhaustive dcmpstat-check-exhaustive dcmrt-check-exhaustive dcmtract-check-exhaustive dcmpmap-check-exhaustive dcmect-check-exhaustive dcmtk-install-doc: $(configdir)/mkinstalldirs $(DESTDIR)$(docdir) - for file in ANNOUNCE CHANGES COPYRIGHT CREDITS FAQ HISTORY VERSION docs/CHANGES.???; do \ + for file in ANNOUNCE COPYRIGHT CREDITS FAQ HISTORY VERSION docs/CHANGES.???; do \ $(INSTALL_DATA) $$file $(DESTDIR)$(docdir) ;\ done @@ -91,7 +91,7 @@ help: @echo "" @echo "The following modules are available:" @echo "" - @echo "ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap" + @echo "ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap dcmect" config-all: (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) @@ -912,6 +912,45 @@ dcmpmap-check: dcmpmap-check-exhaustive: (cd dcmpmap && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) +dcmect-all: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmect-libsrc-all: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmect-tests-all: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmect-install: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmect-install-bin: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmect-install-doc: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmect-install-data: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmect-install-etc: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmect-install-lib: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmect-install-include: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmect-install-support: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmect-check: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmect-check-exhaustive: + (cd dcmect && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + dependencies: -(cd config && $(MAKE) dependencies) (cd ofstd && $(MAKE) dependencies) @@ -934,6 +973,7 @@ dependencies: (cd dcmrt && $(MAKE) dependencies) (cd dcmtract && $(MAKE) dependencies) (cd dcmpmap && $(MAKE) dependencies) + (cd dcmect && $(MAKE) dependencies) clean: (cd ofstd && $(MAKE) clean) @@ -956,6 +996,7 @@ clean: (cd dcmrt && $(MAKE) clean) (cd dcmtract && $(MAKE) clean) (cd dcmpmap && $(MAKE) clean) + (cd dcmect && $(MAKE) clean) (cd doxygen && $(MAKE) clean) -(cd config && $(MAKE) clean) rm -f $(TRASH) @@ -981,6 +1022,7 @@ distclean: (cd dcmrt && $(MAKE) distclean) (cd dcmtract && $(MAKE) distclean) (cd dcmpmap && $(MAKE) distclean) + (cd dcmect && $(MAKE) distclean) (cd doxygen && $(MAKE) distclean) -(cd config && $(MAKE) distclean) rm -f $(TRASH) diff --git a/README b/README index 5dcb0ff6..3d5960dd 100644 --- a/README +++ b/README @@ -9,6 +9,7 @@ DCMTK contains the following sub-packages, each in its own sub-directory: config - configuration utilities for DCMTK dcmdata - a data encoding/decoding library and utility apps + dcmect - a library for working with Enhanced CT objects dcmfg - a library for working with functional groups dcmimage - adds support for color images to dcmimgle dcmimgle - an image processing library and utility apps diff --git a/README.md b/README.md index 51844783..fbe1a3f5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ DCMTK contains the following sub-packages, each in its own sub-directory: - **config** - configuration utilities for DCMTK - **dcmdata** - a data encoding/decoding library and utility apps +- **dcmect** - a library for working with Enhanced CT objects - **dcmfg** - a library for working with functional groups - **dcmimage** - adds support for color images to dcmimgle - **dcmimgle** - an image processing library and utility apps @@ -28,10 +29,10 @@ DCMTK contains the following sub-packages, each in its own sub-directory: Each sub-directory (except _config_) contains further sub-directories for application source code (_apps_), library source code (_libsrc_), library include files (_include_), configuration data (_etc_), documentation (_docs_), sample and support data (_data_) as well as test programs (_tests_). -To build and install the DCMTK package see the [INSTALL](INSTALL) file. For copyright information see the [COPYRIGHT](COPYRIGHT) file. For information about the history of this software see the [HISTORY](HISTORY) file. For answers to frequently asked questions please consult the [FAQ](http://forum.dcmtk.org/faq/). +To build and install the DCMTK package see the [INSTALL](INSTALL) file. For copyright information see the [COPYRIGHT](COPYRIGHT) file. For information about the history of this software see the [HISTORY](HISTORY) file. For answers to frequently asked questions please consult the [FAQ](https://forum.dcmtk.org/faq/). -In addition to the API documentation, which is also available [online](https://support.dcmtk.org/docs/), there is a [Wiki](http://support.dcmtk.org/wiki/) system where further information (e.g. HOWTOs) can be found. +In addition to the API documentation, which is also available [online](https://support.dcmtk.org/docs/), there is a [Wiki](https://support.dcmtk.org/wiki/) system where further information (e.g. HOWTOs) can be found. If you find bugs or other problems with this software, we would appreciate hearing about them. Please send electronic mail to: bugs/at/dcmtk/dot/org -Please try to describe the problem in detail and if possible give a suggested fix. For general questions on how to compile, install or use the toolkit we recommend the [public discussion forum](http://forum.dcmtk.org/). +Please try to describe the problem in detail and if possible give a suggested fix. For general questions on how to compile, install or use the toolkit we recommend the [public discussion forum](https://forum.dcmtk.org/). diff --git a/VERSION b/VERSION index d15b8b06..4f2c1d15 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.6.5 +3.6.6 diff --git a/config/aclocal.m4 b/config/aclocal.m4 index 4641a4c0..05201050 100644 --- a/config/aclocal.m4 +++ b/config/aclocal.m4 @@ -1182,35 +1182,6 @@ else fi ]) - -dnl AC_CHECK_CXX_BOOL checks if bool is a built-in C++ type -dnl (which is not the case on older compilers). - -dnl AC_CHECK_CXX_BOOL(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) -AC_DEFUN(AC_CHECK_CXX_BOOL, -[AC_MSG_CHECKING([if bool is built-in type]) -AH_TEMPLATE([HAVE_CXX_BOOL], [Define if bool is a built-in type.]) -AC_CACHE_VAL(ac_cv_have_cxx_bool, -[AC_TRY_COMPILE([],[ -bool b1 = true; -bool b2 = false; -], -eval "ac_cv_have_cxx_bool=yes", -eval "ac_cv_have_cxx_bool=no")]) -if eval "test \"`echo $ac_cv_have_cxx_bool`\" = yes"; then - AC_MSG_RESULT(yes) -changequote(, )dnl - ac_tr_prototype=HAVE_CXX_BOOL -changequote([, ])dnl - AC_DEFINE_UNQUOTED($ac_tr_prototype) - ifelse([$1], , :, [$1]) -else - AC_MSG_RESULT(no) - ifelse([$2], , , [$2]) -fi -]) - - dnl AC_CHECK_CXX_VOLATILE checks if volatile is a built-in C++ keyword dnl (which is not the case on older compilers). diff --git a/config/configure b/config/configure index 4c04502f..9592c9c7 100755 --- a/config/configure +++ b/config/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for dcmtk 3.6.5. +# Generated by GNU Autoconf 2.69 for dcmtk 3.6.6. # # Report bugs to . # @@ -579,9 +579,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='dcmtk' -PACKAGE_TARNAME='dcmtk-3.6.5' -PACKAGE_VERSION='3.6.5' -PACKAGE_STRING='dcmtk 3.6.5' +PACKAGE_TARNAME='dcmtk-3.6.6' +PACKAGE_VERSION='3.6.6' +PACKAGE_STRING='dcmtk 3.6.6' PACKAGE_BUGREPORT='bugs@dcmtk.org' PACKAGE_URL='http://www.dcmtk.org/' @@ -696,6 +696,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -811,6 +812,7 @@ datadir='${datarootdir}/dcmtk' sysconfdir='${prefix}/etc/dcmtk' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/dcmtk' @@ -1063,6 +1065,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1200,7 +1211,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1313,7 +1324,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures dcmtk 3.6.5 to adapt to many kinds of systems. +\`configure' configures dcmtk 3.6.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1353,6 +1364,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1378,7 +1390,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dcmtk 3.6.5:";; + short | recursive ) echo "Configuration of dcmtk 3.6.6:";; esac cat <<\_ACEOF @@ -1551,7 +1563,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -dcmtk configure 3.6.5 +dcmtk configure 3.6.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2411,7 +2423,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by dcmtk $as_me 3.6.5, which was +It was created by dcmtk $as_me 3.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2833,9 +2845,10 @@ ac_config_headers="$ac_config_headers include/dcmtk/config/osconfig.h" -PACKAGE_VERSION_NUMBER=365 +PACKAGE_VERSION_NUMBER=366 PACKAGE_VERSION_SUFFIX="" -PACKAGE_DATE="2019-10-28" +PACKAGE_DATE="2021-01-14" + cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION_NUMBER ${PACKAGE_VERSION_NUMBER} @@ -13061,7 +13074,7 @@ if ${ac_cv_check_std_namespace+:} false; then : else ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' cat > conftest.$ac_ext < @@ -13533,7 +13546,7 @@ if ${ac_cv_check_class_template+:} false; then : else ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' cat > conftest.$ac_ext < @@ -13605,7 +13618,7 @@ if ${ac_cv_check_static_template_method+:} false; then : else ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' cat > conftest.$ac_ext < conftest.$ac_ext < @@ -13783,49 +13796,6 @@ else $as_echo "no" >&6; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if bool is built-in type" >&5 -$as_echo_n "checking if bool is built-in type... " >&6; } - -if ${ac_cv_have_cxx_bool+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - -bool b1 = true; -bool b2 = false; - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - eval "ac_cv_have_cxx_bool=yes" -else - eval "ac_cv_have_cxx_bool=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -if eval "test \"`echo $ac_cv_have_cxx_bool`\" = yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - ac_tr_prototype=HAVE_CXX_BOOL - cat >>confdefs.h <<_ACEOF -#define $ac_tr_prototype 1 -_ACEOF - - : -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if volatile is known keyword" >&5 $as_echo_n "checking if volatile is known keyword... " >&6; } @@ -17627,7 +17597,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by dcmtk $as_me 3.6.5, which was +This file was extended by dcmtk $as_me 3.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17690,7 +17660,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -dcmtk config.status 3.6.5 +dcmtk config.status 3.6.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/config/configure.in b/config/configure.in index 3c84bc53..dfd23217 100644 --- a/config/configure.in +++ b/config/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(dcmtk, 3.6.5, [bugs@dcmtk.org], [dcmtk-3.6.5], [http://www.dcmtk.org/]) +AC_INIT(dcmtk, 3.6.6, [bugs@dcmtk.org], [dcmtk-3.6.6], [http://www.dcmtk.org/]) AC_PREREQ(2.60) AC_CONFIG_SRCDIR(Makefile.in) AC_CONFIG_HEADERS(include/dcmtk/config/osconfig.h) @@ -10,9 +10,9 @@ dnl ------------------------------------------------------- dnl Additional Package Information dnl ------------------------------------------------------- -PACKAGE_VERSION_NUMBER=365 +PACKAGE_VERSION_NUMBER=366 PACKAGE_VERSION_SUFFIX="" -PACKAGE_DATE="2019-10-28" +PACKAGE_DATE="2021-01-14" AC_DEFINE_UNQUOTED(PACKAGE_VERSION_NUMBER,${PACKAGE_VERSION_NUMBER},[Define to the version number of this package.]) AC_DEFINE_UNQUOTED(PACKAGE_VERSION_SUFFIX,"${PACKAGE_VERSION_SUFFIX}",[Define to the version suffix of this package.]) AC_DEFINE_UNQUOTED(PACKAGE_DATE,"${PACKAGE_DATE}",[Define to the release date of this package.]) @@ -917,7 +917,6 @@ AC_CHECK_CLASS_TEMPLATE AC_CHECK_STATIC_TEMPLATE_METHOD AC_CHECK_FUNCTION_TEMPLATE AC_CHECK_EXPLICIT_TEMPLATE_SPECIALIZATION -AC_CHECK_CXX_BOOL AC_CHECK_CXX_VOLATILE AC_CXX_TYPENAME AC_STDIO_NAMESPACE diff --git a/config/confmod b/config/confmod index b7fff7da..e36db180 100755 --- a/config/confmod +++ b/config/confmod @@ -608,6 +608,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -672,6 +673,7 @@ datadir='${datarootdir}/dcmtk' sysconfdir='${prefix}/etc/dcmtk' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/dcmtk' @@ -924,6 +926,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1061,7 +1072,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1214,6 +1225,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] diff --git a/config/docs/macros.txt b/config/docs/macros.txt index 86c49193..5da0ea2f 100644 --- a/config/docs/macros.txt +++ b/config/docs/macros.txt @@ -46,6 +46,15 @@ DCMTK_BUILD_IN_PROGRESS define this macro yourself since this is done automatically by the build system. +DCMTK_UNDEF_SANITIZER + Affected: all modules + Type of modification: Toolkit customization + Explanation: When compiling with the GCC undefined behavior sanitizer + (-fsanitize=undefined), this macro must be defined to disable certain code + in config/tests/arith.cc that would otherwise trigger a runtime error to be + raised by the sanitizer and thus prevent the CMake configure phase from + completing. + DCMTK_ENABLE_UNSAFE_VSNPRINTF Affected: ofstd Type of modification: Activates feature @@ -191,6 +200,18 @@ ENABLE_BUILTIN_DICTIONARY builtin dictionary stays empty. For further information about dictionary configuration read dcmdata/docs/datadict.txt. +ENABLE_DCMJPLS_INTERLEAVE_NONE + Affected: dcmjpls + Type of modification: Enables feature + Explanation: Re-enables the option for uninterleaved encoding + (--interleave-none) in the JPEG-LS encoder on command line and library + level. This option was removed after DCMTK 3.6.5 since it may in certain + cases (color image with BitsStored > 12) create compressed images that + are correct but cannot be decoded by the JPEG-LS library due to a known + bug (DCMTK issue #892). The option will be re-enabled permanently once + DCMTK has been ported to CharLS 2.x, another branch of the JPEG-LS + library that requires a C++14 compiler, however. + ENABLE_EXTERNAL_DICTIONARY Affected: dcmdata Type of modification: Enables feature @@ -332,6 +353,9 @@ SITE_UID_ROOT namespace should compile DCMTK with SITE_UID_ROOT defined to their own UID root. Please make sure that the resulting UIDs do not exceed the 64 characters limit! + DCMTK may add a maximum of 44 characters to the UID root when + generating UIDs. Therefore, the root must not be longer than 20 + characters in order to avoid UID truncation. STARVIEW Affected: dcmimgle, dcmimage diff --git a/config/include/dcmtk/config/osconfig.h.in b/config/include/dcmtk/config/osconfig.h.in index 006750e1..fcde418d 100644 --- a/config/include/dcmtk/config/osconfig.h.in +++ b/config/include/dcmtk/config/osconfig.h.in @@ -173,9 +173,6 @@ /* define if the compiler supports basic C++11 syntax */ #undef HAVE_CXX11 -/* Define if bool is a built-in type. */ -#undef HAVE_CXX_BOOL - /* Define if volatile is a known keyword */ #undef HAVE_CXX_VOLATILE diff --git a/config/modules b/config/modules index 16768209..20298ba5 100644 --- a/config/modules +++ b/config/modules @@ -1 +1 @@ -ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap +ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap dcmect diff --git a/config/rootconf b/config/rootconf index f3c69db3..a61d0e02 100755 --- a/config/rootconf +++ b/config/rootconf @@ -84,7 +84,7 @@ check-nosilent-exhaustive: $makecheckexhaustive dcmtk-install-doc: \$(configdir)/mkinstalldirs \$(DESTDIR)\$(docdir) - for file in ANNOUNCE CHANGES COPYRIGHT CREDITS FAQ HISTORY VERSION docs/CHANGES.???; do \\ + for file in ANNOUNCE COPYRIGHT CREDITS FAQ HISTORY VERSION docs/CHANGES.???; do \\ \$(INSTALL_DATA) \$\$file \$(DESTDIR)\$(docdir) ;\\ done diff --git a/config/tests/arith.cc b/config/tests/arith.cc index c2cdd9db..12371170 100644 --- a/config/tests/arith.cc +++ b/config/tests/arith.cc @@ -189,7 +189,13 @@ static void divide_by_zero() // away or emit compile-time errors. volatile T t0 = 1; volatile T t1 = 0; +#ifndef DCMTK_UNDEF_SANITIZER + // disable this line when compiling with gcc -fsanitize=undefined + // by defining DCMTK_UNDEF_SANITIZER because otherwise this + // program will be aborted with a runtime error, thus preventing + // CMake from creating the makefiles / project files. t0 /= t1; +#endif } // gathers and prints information for integer types @@ -353,9 +359,14 @@ static void provoke_snan() // we assign a signaling NaN to another float variable // and convert it to a quiet NaN. volatile T t = guess::snan(); - // Other compilers will trigger only if we use - // arithmetics. + // Other compilers will trigger only if we use arithmetics. +#ifndef DCMTK_UNDEF_SANITIZER + // disable this line when compiling with gcc -fsanitize=undefined + // by defining DCMTK_UNDEF_SANITIZER because otherwise this + // program will be aborted with a runtime error, thus preventing + // CMake from creating the makefiles / project files. ++t; +#endif } template diff --git a/config/tests/stack.cc b/config/tests/stack.cc index bbb8e752..27399289 100644 --- a/config/tests/stack.cc +++ b/config/tests/stack.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017, OFFIS e.V. + * Copyright (C) 2017-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by diff --git a/dcmdata/apps/dcm2json.cc b/dcmdata/apps/dcm2json.cc index 14d4321d..db97e15e 100644 --- a/dcmdata/apps/dcm2json.cc +++ b/dcmdata/apps/dcm2json.cc @@ -1,6 +1,6 @@ /* * -* Copyright (C) 2016-2017, OFFIS e.V. +* Copyright (C) 2016-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,7 @@ #include "dcmtk/dcmdata/dcjson.h" #include "dcmtk/ofstd/ofstream.h" #include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofexit.h" #ifdef WITH_ZLIB #include /* for zlibVersion() */ @@ -38,6 +39,9 @@ #define OFFIS_CONSOLE_APPLICATION "dcm2json" #define OFFIS_CONSOLE_DESCRIPTION "Convert DICOM file and data set to JSON" +#define EXITCODE_CANNOT_CONVERT_TO_UNICODE 80 +#define EXITCODE_CANNOT_WRITE_VALID_JSON 81 + static OFLogger dcm2jsonLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" @@ -51,32 +55,29 @@ static OFCondition writeFile(STD_NAMESPACE ostream &out, DcmFileFormat *dfile, const E_FileReadMode readMode, const OFBool format, - const OFBool printMetaInfo) + const OFBool printMetaInfo, + const OFBool encode_extended) { OFCondition result = EC_IllegalParameter; if ((ifname != NULL) && (dfile != NULL)) { - DcmDataset *dset = dfile->getDataset(); - /* write JSON document content */ - - if (readMode == ERM_dataset) + DcmDataset *dset = dfile->getDataset(); + if (format) { - result = format - ? - dset->writeJson(out, DcmJsonFormatPretty(printMetaInfo)) - : - dset->writeJson(out, DcmJsonFormatCompact(printMetaInfo)) - ; + DcmJsonFormatPretty fmt(printMetaInfo); + fmt.setJsonExtensionEnabled(encode_extended); + if (readMode == ERM_dataset) + result = dset->writeJsonExt(out, fmt, OFTrue, OFTrue); + else result = dfile->writeJson(out, fmt); } else { - result = format - ? - dfile->writeJson(out, DcmJsonFormatPretty(printMetaInfo)) - : - dfile->writeJson(out, DcmJsonFormatCompact(printMetaInfo)) - ; + DcmJsonFormatCompact fmt(printMetaInfo); + fmt.setJsonExtensionEnabled(encode_extended); + if (readMode == ERM_dataset) + result = dset->writeJsonExt(out, fmt, OFTrue, OFTrue); + else result = dfile->writeJson(out, fmt); } } return result; @@ -89,7 +90,7 @@ int main(int argc, char *argv[]) { OFBool opt_format = OFTrue; OFBool opt_addMetaInformation = OFFalse; - + OFBool opt_encode_extended = OFFalse; E_FileReadMode opt_readMode = ERM_autoDetect; E_TransferSyntax opt_ixfer = EXS_Unknown; OFString optStr; @@ -119,6 +120,11 @@ int main(int argc, char *argv[]) cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addGroup("processing options:"); + cmd.addSubGroup("encoding of infinity and not-a-number:"); + cmd.addOption("--encode-strict", "-es", "report error for 'inf' and 'nan' (default)"); + cmd.addOption("--encode-extended", "-ee", "permit 'inf' and 'nan' in JSON numbers"); + cmd.addGroup("output options:"); cmd.addSubGroup("output format:"); cmd.addOption("--formatted-code", "+fc", "enable whitespace formatting (default)"); @@ -183,6 +189,14 @@ int main(int argc, char *argv[]) } cmd.endOptionBlock(); + /* number encoding options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--encode-strict")) + opt_encode_extended = OFFalse; + if (cmd.findOption("--encode-extended")) + opt_encode_extended = OFTrue; + cmd.endOptionBlock(); + /* format options */ cmd.beginOptionBlock(); if (cmd.findOption("--formatted-code")) @@ -234,11 +248,11 @@ int main(int argc, char *argv[]) if (status.bad()) { OFLOG_FATAL(dcm2jsonLogger, status.text() << ": converting file to UTF-8: " << ifname); - result = 4; + result = EXITCODE_CANNOT_CONVERT_TO_UNICODE; } #else OFLOG_FATAL(dcm2jsonLogger, "character set conversion not available"); - return 4; + result = EXITCODE_CANNOT_CONVERT_TO_UNICODE; #endif } } @@ -253,25 +267,38 @@ int main(int argc, char *argv[]) if (stream.good()) { /* write content in JSON format to file */ - if (writeFile(stream, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation).bad()) - result = 2; + status = writeFile(stream, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation, opt_encode_extended); + if (status.bad()) + { + OFLOG_FATAL(dcm2jsonLogger, status.text() << ": " << ifname); + result = EXITCODE_CANNOT_WRITE_VALID_JSON; + } } else - result = 1; + result = EXITCODE_CANNOT_WRITE_OUTPUT_FILE; } else { /* write content in JSON format to standard output */ - if (writeFile(COUT, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation).bad()) - result = 3; + status = writeFile(COUT, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation, opt_encode_extended); + if (status.bad()) + { + OFLOG_FATAL(dcm2jsonLogger, status.text() << ": " << ifname); + result = EXITCODE_CANNOT_WRITE_VALID_JSON; + } } } } else + { OFLOG_ERROR(dcm2jsonLogger, OFFIS_CONSOLE_APPLICATION << ": error (" << status.text() << ") reading file: " << ifname); + return EXITCODE_CANNOT_READ_INPUT_FILE; + } } else + { OFLOG_ERROR(dcm2jsonLogger, OFFIS_CONSOLE_APPLICATION << ": invalid filename: "); - + return EXITCODE_NO_INPUT_FILES; + } return result; } diff --git a/dcmdata/apps/dcmconv.cc b/dcmdata/apps/dcmconv.cc index 8acab661..0930cdab 100644 --- a/dcmdata/apps/dcmconv.cc +++ b/dcmdata/apps/dcmconv.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) const char *opt_ofname = NULL; E_FileReadMode opt_readMode = ERM_autoDetect; - E_FileWriteMode opt_writeMode = EWM_fileformat; + E_FileWriteMode opt_writeMode = EWM_createNewMeta; E_TransferSyntax opt_ixfer = EXS_Unknown; E_TransferSyntax opt_oxfer = EXS_Unknown; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; @@ -189,8 +189,8 @@ int main(int argc, char *argv[]) cmd.addGroup("output options:"); cmd.addSubGroup("output file format:"); - cmd.addOption("--write-file", "+F", "write file format (default)"); - cmd.addOption("--write-new-meta-info", "+Fm", "write file format with new meta information"); + cmd.addOption("--write-new-meta-info", "+Fm", "write file format\nwith new meta information (default)"); + cmd.addOption("--write-file", "+F", "write file format"); cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); cmd.addSubGroup("output transfer syntax:"); cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); diff --git a/dcmdata/apps/dump2dcm.cc b/dcmdata/apps/dump2dcm.cc index a863df79..81e6cdf9 100644 --- a/dcmdata/apps/dump2dcm.cc +++ b/dcmdata/apps/dump2dcm.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2017, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -15,7 +15,7 @@ * * Author: Andreas Barth * - * Purpose: create a Dicom FileFormat or DataSet from an ASCII-dump + * Purpose: create a DICOM FileFormat or DataSet from an ASCII-dump * */ @@ -34,8 +34,8 @@ * two characters. If the VR can determined from the tag, this part * of a line is optional. * Value: There are several rules for writing values: - * 1. US, SS, SL, UL, FD, FL, OD, OF and OL are written as decimal - * strings that can be read by scanf(). + * 1. US, SS, UL, SL, UV, SV, FD, FL, OD, OF, OL and OV are written as + * decimal strings that can be read by scanf(). * 2. AT is written as '(gggg,eeee)' with additional spaces stripped * off automatically and gggg and eeee being decimal strings that * can be read by scanf(). @@ -455,6 +455,8 @@ putFileContentsIntoElement(DcmElement *elem, const char *filename) ec = EC_IllegalCall; if (ec.good()) { + OFLOG_INFO(dump2dcmLogger, "reading " << len << " bytes from binary data file: " << filename); + OFLOG_DEBUG(dump2dcmLogger, " and storing it in the element " << elem->getTag()); /* read binary file into the buffer */ if (fread(buf, 1, len, f) != len) { @@ -505,7 +507,7 @@ insertIntoSet(DcmStack &stack, const E_TransferSyntax xfer, const DcmTagKey &tag (tagkey != DCM_LUTData || (vr != EVR_US && vr != EVR_SS && vr != EVR_OW)) && (tagkey != DCM_PixelData || (vr != EVR_OB && vr != EVR_OW && vr != EVR_pixelSQ)) && (tagvr != EVR_xs || (vr != EVR_US && vr != EVR_SS)) && - (tagvr != EVR_ox || (vr != EVR_OB && vr != EVR_OW)) && + ((tagvr != EVR_ox && tagvr != EVR_px) || (vr != EVR_OB && vr != EVR_OW)) && (tagvr != EVR_na || vr != EVR_pixelItem)) { OFLOG_WARN(dump2dcmLogger, "Tag " << tag << " with wrong VR '" diff --git a/dcmdata/apps/img2dcm.cc b/dcmdata/apps/img2dcm.cc index e547b5ea..141e0511 100644 --- a/dcmdata/apps/img2dcm.cc +++ b/dcmdata/apps/img2dcm.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2013, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -188,7 +188,7 @@ static OFCondition startConversion(OFCommandLine& cmd, OFCmdUnsignedInt filepad = 0; // Item pad length for output DICOM file OFCmdUnsignedInt itempad = 0; - // Write only pure dataset, i.e. without meta header + // Write file format (with meta header) E_FileWriteMode writeMode = EWM_fileformat; // Override keys are applied at the very end of the conversion "pipeline" OFList overrideKeys; diff --git a/dcmdata/apps/mdfdsman.cc b/dcmdata/apps/mdfdsman.cc index 61187c9a..e5a6ea11 100644 --- a/dcmdata/apps/mdfdsman.cc +++ b/dcmdata/apps/mdfdsman.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2003-2017, OFFIS e.V. + * Copyright (C) 2003-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -481,10 +481,10 @@ OFCondition MdfDatasetManager::modifyAllTags(OFString tag_path, DcmStack result_stack; DcmObject *elem; // get references to all matching tags in dataset and store them in stack - OFLOG_DEBUG(mdfdsmanLogger, "looking for occurences of: " << key.toString()); + OFLOG_DEBUG(mdfdsmanLogger, "looking for occurrences of: " << key.toString()); result=dset->findAndGetElements(key, result_stack); // if there are elements found, modify metaheader if necessary - OFLOG_DEBUG(mdfdsmanLogger, "found " << result_stack.card() << " occurences"); + OFLOG_DEBUG(mdfdsmanLogger, "found " << result_stack.card() << " occurrences"); // as long there are matching elements left on the stack while( result_stack.card() > 0 && result.good() ) { @@ -652,7 +652,7 @@ OFCondition MdfDatasetManager::saveFile(const char *file_name, opt_padenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), - (opt_dataset) ? EWM_dataset : EWM_fileformat); + (opt_dataset) ? EWM_dataset : EWM_createNewMeta); } else { OFLOG_DEBUG(mdfdsmanLogger, "no conversion to transfer syntax " << DcmXfer(opt_xfer).getXferName() << " possible!"); diff --git a/dcmdata/apps/xml2dcm.cc b/dcmdata/apps/xml2dcm.cc index 6392fb9d..2961d5bd 100644 --- a/dcmdata/apps/xml2dcm.cc +++ b/dcmdata/apps/xml2dcm.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2003-2019, OFFIS e.V. + * Copyright (C) 2003-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -224,7 +224,7 @@ static OFCondition createNewElement(xmlNodePtr current, if ((tagEVR != dcmEVR) && (dcmEVR != EVR_UNKNOWN) && (tagEVR != EVR_UNKNOWN) && ((dcmTagKey != DCM_LUTData) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS) && (dcmEVR != EVR_OW))) && ((tagEVR != EVR_xs) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS))) && - ((tagEVR != EVR_ox) || ((dcmEVR != EVR_OB) && (dcmEVR != EVR_OW)))) + (((tagEVR != EVR_ox) && (tagEVR != EVR_px)) || ((dcmEVR != EVR_OB) && (dcmEVR != EVR_OW)))) { OFLOG_WARN(xml2dcmLogger, "tag " << dcmTag << " has wrong VR (" << dcmVR.getVRName() << "), correct is " << dcmTag.getVR().getVRName()); @@ -309,6 +309,8 @@ static OFCondition putElementContent(xmlNodePtr current, result = element->createUint8Array(OFstatic_cast(Uint32, buflen), buf); if (result.good()) { + OFLOG_INFO(xml2dcmLogger, "reading " << fileSize << " bytes from binary data file: " << filename); + OFLOG_DEBUG(xml2dcmLogger, " and storing it in the element " << element->getTag()); /* read binary file into the buffer */ if (fread(buf, 1, OFstatic_cast(size_t, fileSize), f) != fileSize) { @@ -339,6 +341,8 @@ static OFCondition putElementContent(xmlNodePtr current, /* set the value of the newly created element */ result = element->putString(OFreinterpret_cast(char *, elemVal)); } + if (result.bad()) + OFLOG_ERROR(xml2dcmLogger, "cannot put content to element " << element->getTag() << ": " << result.text()); } /* free allocated memory */ xmlFree(elemVal); diff --git a/dcmdata/data/SC.dump b/dcmdata/data/SC.dump index 66ec3ab8..4b5cd861 100644 --- a/dcmdata/data/SC.dump +++ b/dcmdata/data/SC.dump @@ -5,7 +5,7 @@ ################################################################################ # Type 1: Value MUST be filled in # # Type 1C: Value MUST be filled in if known, if certain condition (see # -# standard) is fullfilled, otherwise DO NOT insert # +# standard) is fulfilled, otherwise DO NOT insert # # Type 2: Value MUST be filled in if known, MUST be left empty otherwise # # Type 2C: Same as 2, if a certain condition (see standard) is met. If the # # condition is not met, DO NOT insert # diff --git a/dcmdata/data/VLP.dump b/dcmdata/data/VLP.dump index 271ca536..342dfd8c 100644 --- a/dcmdata/data/VLP.dump +++ b/dcmdata/data/VLP.dump @@ -5,7 +5,7 @@ ################################################################################ # Type 1: Value MUST be filled in # # Type 1C: Value MUST be filled in if known, if certain condition (see # -# standard) is fullfilled, otherwise LEAVE OUT line # +# standard) is fulfilled, otherwise LEAVE OUT line # # Type 2: Value MUST be filled in if known, MUST be left empty otherwise # # Type 2C: Same as 2, if a certain condition (see standard) is met. If the # # condition is not met, LEAVE OUT line # diff --git a/dcmdata/data/dicom.dic b/dcmdata/data/dicom.dic index cb5c19bc..69863949 100644 --- a/dcmdata/data/dicom.dic +++ b/dcmdata/data/dicom.dic @@ -1,5 +1,5 @@ # -# Copyright (C) 1994-2019, OFFIS e.V. +# Copyright (C) 1994-2020, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by @@ -21,13 +21,12 @@ # DICONDE (Digital Imaging and Communication in Nondestructive Evaluation) and # DICOS (Digital Imaging and Communications in Security) standard. # -# Generated automatically from DICOM PS 3.6-2019b and PS 3.7-2019b -# File created on 2019-04-26 14:51:35 by J. Riesmeier on thinkpad. -# File updated manually on 2019-08-07 by J. Riesmeier +# Generated automatically from DICOM PS 3.6-2020e and PS 3.7-2020e +# File created on 2020-11-24 14:44:39 by J. Riesmeier on thinkpad. # # In addition, the data dictionary entries from the following final text # supplements and correction items (CP) have been incorporated: -# - Supplement 175 (FT2) +# - (none) # # Each line represents an entry in the data dictionary. Each line has 5 fields # (Tag, VR, Name, VM, Version). Entries need not be in ascending tag order. @@ -80,6 +79,16 @@ (0002,0016) AE SourceApplicationEntityTitle 1 DICOM (0002,0017) AE SendingApplicationEntityTitle 1 DICOM (0002,0018) AE ReceivingApplicationEntityTitle 1 DICOM +(0002,0026) UR SourcePresentationAddress 1 DICOM +(0002,0027) UR SendingPresentationAddress 1 DICOM +(0002,0028) UR ReceivingPresentationAddress 1 DICOM +(0002,0031) OB RTVMetaInformationVersion 1 DICOM +(0002,0032) UI RTVCommunicationSOPClassUID 1 DICOM +(0002,0033) UI RTVCommunicationSOPInstanceUID 1 DICOM +(0002,0035) OB RTVSourceIdentifier 1 DICOM +(0002,0036) OB RTVFlowIdentifier 1 DICOM +(0002,0037) UL RTVFlowRTPSamplingRate 1 DICOM +(0002,0038) FD RTVFlowActualFrameDuration 1 DICOM (0002,0100) UI PrivateInformationCreatorUID 1 DICOM (0002,0102) OB PrivateInformation 1 DICOM (0004,1130) CS FileSetID 1 DICOM @@ -99,6 +108,7 @@ (0004,1511) UI ReferencedSOPInstanceUIDInFile 1 DICOM (0004,1512) UI ReferencedTransferSyntaxUIDInFile 1 DICOM (0004,151A) UI ReferencedRelatedGeneralSOPClassUIDInFile 1-n DICOM +(0006,0001) SQ CurrentFrameFunctionalGroupsSequence 1 DICOM (0008,0005) CS SpecificCharacterSet 1-n DICOM (0008,0006) SQ LanguageCodeSequence 1 DICOM (0008,0008) CS ImageType 2-n DICOM @@ -262,6 +272,7 @@ (0008,2228) SQ PrimaryAnatomicStructureSequence 1 DICOM (0008,2230) SQ PrimaryAnatomicStructureModifierSequence 1 DICOM (0008,3001) SQ AlternateRepresentationSequence 1 DICOM +(0008,3002) UI AvailableTransferSyntaxUID 1-n DICOM (0008,3010) UI IrradiationEventUID 1-n DICOM (0008,3011) SQ SourceIrradiationEventSequence 1 DICOM (0008,3012) UI RadiopharmaceuticalAdministrationEventUID 1 DICOM @@ -673,6 +684,11 @@ (0016,008C) OB GPSAreaInformation 1 DICOM (0016,008D) DT GPSDateStamp 1 DICOM (0016,008E) IS GPSDifferential 1 DICOM +(0016,1001) CS LightSourcePolarization 1 DICOM +(0016,1002) DS EmitterColorTemperature 1 DICOM +(0016,1003) CS ContactMethod 1 DICOM +(0016,1004) CS ImmersionMedia 1-n DICOM +(0016,1005) DS OpticalMagnificationFactor 1 DICOM (0018,0010) LO ContrastBolusAgent 1 DICOM (0018,0012) SQ ContrastBolusAgentSequence 1 DICOM (0018,0013) FL ContrastBolusT1Relaxivity 1 DICOM @@ -730,6 +746,7 @@ (0018,1008) LO GantryID 1 DICOM (0018,1009) UT UniqueDeviceIdentifier 1 DICOM (0018,100A) SQ UDISequence 1 DICOM +(0018,100B) UI ManufacturerDeviceClassUID 1-n DICOM (0018,1010) LO SecondaryCaptureDeviceID 1 DICOM (0018,1012) DA DateOfSecondaryCapture 1 DICOM (0018,1014) TM TimeOfSecondaryCapture 1 DICOM @@ -890,6 +907,15 @@ (0018,1622) US ShutterPresentationValue 1 DICOM (0018,1623) US ShutterOverlayGroup 1 DICOM (0018,1624) US ShutterPresentationColorCIELabValue 3 DICOM +(0018,1630) CS OutlineShapeType 1 DICOM +(0018,1631) FD OutlineLeftVerticalEdge 1 DICOM +(0018,1632) FD OutlineRightVerticalEdge 1 DICOM +(0018,1633) FD OutlineUpperHorizontalEdge 1 DICOM +(0018,1634) FD OutlineLowerHorizontalEdge 1 DICOM +(0018,1635) FD CenterOfCircularOutline 2 DICOM +(0018,1636) FD DiameterOfCircularOutline 1 DICOM +(0018,1637) UL NumberOfPolygonalVertices 1 DICOM +(0018,1638) OF VerticesOfThePolygonalOutline 1 DICOM (0018,1700) CS CollimatorShape 1-3 DICOM (0018,1702) IS CollimatorLeftVerticalEdge 1 DICOM (0018,1704) IS CollimatorRightVerticalEdge 1 DICOM @@ -925,6 +951,7 @@ (0018,3105) IS LesionNumber 1-n DICOM (0018,5000) SH OutputPower 1-n DICOM (0018,5010) LO TransducerData 1-n DICOM +(0018,5011) SQ TransducerIdentificationSequence 1 DICOM (0018,5012) DS FocusDepth 1 DICOM (0018,5020) LO ProcessingFunction 1 DICOM (0018,5022) DS MechanicalIndex 1 DICOM @@ -2039,6 +2066,18 @@ (0032,1066) UT ReasonForVisit 1 DICOM (0032,1067) SQ ReasonForVisitCodeSequence 1 DICOM (0032,1070) LO RequestedContrastAgent 1 DICOM +(0034,0001) SQ FlowIdentifierSequence 1 DICOM +(0034,0002) OB FlowIdentifier 1 DICOM +(0034,0003) UI FlowTransferSyntaxUID 1 DICOM +(0034,0004) UL FlowRTPSamplingRate 1 DICOM +(0034,0005) OB SourceIdentifier 1 DICOM +(0034,0007) OB FrameOriginTimestamp 1 DICOM +(0034,0008) CS IncludesImagingSubject 1 DICOM +(0034,0009) SQ FrameUsefulnessGroupSequence 1 DICOM +(0034,000A) SQ RealTimeBulkDataFlowSequence 1 DICOM +(0034,000B) SQ CameraPositionGroupSequence 1 DICOM +(0034,000C) CS IncludesInformation 1 DICOM +(0034,000D) SQ TimeOfFrameGroupSequence 1 DICOM (0038,0004) SQ ReferencedPatientAliasSequence 1 DICOM (0038,0008) CS VisitStatusID 1 DICOM (0038,0010) LO AdmissionID 1 DICOM @@ -2096,6 +2135,13 @@ (003A,0300) SQ MultiplexedAudioChannelsDescriptionCodeSequence 1 DICOM (003A,0301) IS ChannelIdentificationCode 1 DICOM (003A,0302) CS ChannelMode 1 DICOM +(003A,0310) UI MultiplexGroupUID 1 DICOM +(003A,0311) DS PowerlineFrequency 1 DICOM +(003A,0312) SQ ChannelImpedanceSequence 1 DICOM +(003A,0313) DS ImpedanceValue 1 DICOM +(003A,0314) DT ImpedanceMeasurementDateTime 1 DICOM +(003A,0315) DS ImpedanceMeasurementFrequency 1 DICOM +(003A,0316) CS ImpedanceMeasurementCurrentType 1 DICOM (0040,0001) AE ScheduledStationAETitle 1-n DICOM (0040,0002) DA ScheduledProcedureStepStartDate 1 DICOM (0040,0003) TM ScheduledProcedureStepStartTime 1 DICOM @@ -2305,6 +2351,14 @@ (0040,A504) SQ ContentTemplateSequence 1 DICOM (0040,A525) SQ IdenticalDocumentsSequence 1 DICOM (0040,A730) SQ ContentSequence 1 DICOM +(0040,A801) SQ TabulatedValuesSequence 1 DICOM +(0040,A802) UL NumberOfTableRows 1 DICOM +(0040,A803) UL NumbeOfTableColumns 1 DICOM +(0040,A804) UL TableRowNumber 1 DICOM +(0040,A805) UL TableColumnNumber 1 DICOM +(0040,A806) SQ TableRowDefinitionSequence 1 DICOM +(0040,A807) SQ TableColumnDefinitionSequence 1 DICOM +(0040,A808) SQ CellValuesSequence 1 DICOM (0040,B020) SQ WaveformAnnotationSequence 1 DICOM (0040,DB00) CS TemplateIdentifier 1 DICOM (0040,DB73) UL ReferencedContentItemIdentifier 1-n DICOM @@ -2769,6 +2823,8 @@ (0068,7001) CS ModelModification 1 DICOM (0068,7002) CS ModelMirroring 1 DICOM (0068,7003) SQ ModelUsageCodeSequence 1 DICOM +(0068,7004) UI ModelGroupUID 1 DICOM +(0068,7005) UR RelativeURIReferenceWithinEncapsulatedDocument 1 DICOM (0070,0001) SQ GraphicAnnotationSequence 1 DICOM (0070,0002) CS GraphicLayer 1 DICOM (0070,0003) CS BoundingBoxAnnotationUnits 1 DICOM @@ -3009,6 +3065,9 @@ (0072,007E) SS SelectorSSValue 1-n DICOM (0072,007F) UI SelectorUIValue 1-n DICOM (0072,0080) SQ SelectorCodeSequenceValue 1 DICOM +(0072,0081) OV SelectorOVValue 1 DICOM +(0072,0082) SV SelectorSVValue 1-n DICOM +(0072,0083) UV SelectorUVValue 1-n DICOM (0072,0100) US NumberOfScreens 1 DICOM (0072,0102) SQ NominalScreenDefinitionSequence 1 DICOM (0072,0104) US NumberOfVerticalPixels 1 DICOM @@ -3431,6 +3490,9 @@ (3006,00B8) FL ROIElementalCompositionAtomicMassFraction 1 DICOM (3006,00C6) DS FrameOfReferenceTransformationMatrix 16 DICOM (3006,00C8) LO FrameOfReferenceTransformationComment 1 DICOM +(3006,00C9) SQ PatientLocationCoordinatesSequence 1 DICOM +(3006,00CA) SQ PatientLocationCoordinatesCodeSequence 1 DICOM +(3006,00CB) SQ PatientSupportPositionSequence 1 DICOM (3008,0010) SQ MeasuredDoseReferenceSequence 1 DICOM (3008,0012) ST MeasuredDoseDescription 1 DICOM (3008,0014) CS MeasuredDoseType 1 DICOM @@ -3580,7 +3642,6 @@ (300A,007A) IS RepeatFractionCycleLength 1 DICOM (300A,007B) LT FractionPattern 1 DICOM (300A,0080) IS NumberOfBeams 1 DICOM -(300A,0082) DS BeamDoseSpecificationPoint 3 DICOM (300A,0083) UI ReferencedDoseReferenceUID 1 DICOM (300A,0084) DS BeamDose 1 DICOM (300A,0086) DS BeamMeterset 1 DICOM @@ -3879,6 +3940,7 @@ (300A,0395) CS ScanSpotReorderingAllowed 1 DICOM (300A,0396) FL ScanSpotMetersetWeights 1-n DICOM (300A,0398) FL ScanningSpotSize 2 DICOM +(300A,0399) FL ScanSpotSizesDelivered 2-2n DICOM (300A,039A) IS NumberOfPaintings 1 DICOM (300A,03A0) SQ IonToleranceTableSequence 1 DICOM (300A,03A2) SQ IonBeamSequence 1 DICOM @@ -3897,6 +3959,7 @@ (300A,0423) CS GeneralAccessoryType 1 DICOM (300A,0424) IS GeneralAccessoryNumber 1 DICOM (300A,0425) FL SourceToGeneralAccessoryDistance 1 DICOM +(300A,0426) DS IsocenterToGeneralAccessoryDistance 1 DICOM (300A,0431) SQ ApplicatorGeometrySequence 1 DICOM (300A,0432) CS ApplicatorApertureShape 1 DICOM (300A,0433) FL ApplicatorOpening 1 DICOM @@ -3923,6 +3986,185 @@ (300A,0510) FL DeliveredNominalRangeModulatedRegionDepths 2 DICOM (300A,0511) CS DeliveredReferenceDoseDefinition 1 DICOM (300A,0512) CS ReferenceDoseDefinition 1 DICOM +(300A,0600) US RTControlPointIndex 1 DICOM +(300A,0601) US RadiationGenerationModeIndex 1 DICOM +(300A,0602) US ReferencedDefinedDeviceIndex 1 DICOM +(300A,0603) US RadiationDoseIdentificationIndex 1 DICOM +(300A,0604) US NumberOfRTControlPoints 1 DICOM +(300A,0605) US ReferencedRadiationGenerationModeIndex 1 DICOM +(300A,0606) US TreatmentPositionIndex 1 DICOM +(300A,0607) US ReferencedDeviceIndex 1 DICOM +(300A,0608) LO TreatmentPositionGroupLabel 1 DICOM +(300A,0609) UI TreatmentPositionGroupUID 1 DICOM +(300A,060A) SQ TreatmentPositionGroupSequence 1 DICOM +(300A,060B) US ReferencedTreatmentPositionIndex 1 DICOM +(300A,060C) US ReferencedRadiationDoseIdentificationIndex 1 DICOM +(300A,060D) FD RTAccessoryHolderWaterEquivalentThickness 1 DICOM +(300A,060E) US ReferencedRTAccessoryHolderDeviceIndex 1 DICOM +(300A,060F) CS RTAccessoryHolderSlotExistenceFlag 1 DICOM +(300A,0610) SQ RTAccessoryHolderSlotSequence 1 DICOM +(300A,0611) LO RTAccessoryHolderSlotID 1 DICOM +(300A,0612) FD RTAccessoryHolderSlotDistance 1 DICOM +(300A,0613) FD RTAccessorySlotDistance 1 DICOM +(300A,0614) SQ RTAccessoryHolderDefinitionSequence 1 DICOM +(300A,0615) LO RTAccessoryDeviceSlotID 1 DICOM +(300A,0616) SQ RTRadiationSequence 1 DICOM +(300A,0617) SQ RadiationDoseSequence 1 DICOM +(300A,0618) SQ RadiationDoseIdentificationSequence 1 DICOM +(300A,0619) LO RadiationDoseIdentificationLabel 1 DICOM +(300A,061A) CS ReferenceDoseType 1 DICOM +(300A,061B) CS PrimaryDoseValueIndicator 1 DICOM +(300A,061C) SQ DoseValuesSequence 1 DICOM +(300A,061D) CS DoseValuePurpose 1-n DICOM +(300A,061E) FD ReferenceDosePointCoordinates 3 DICOM +(300A,061F) SQ RadiationDoseValuesParametersSequence 1 DICOM +(300A,0620) SQ MetersetToDoseMappingSequence 1 DICOM +(300A,0621) SQ ExpectedInVivoMeasurementValuesSequence 1 DICOM +(300A,0622) US ExpectedInVivoMeasurementValueIndex 1 DICOM +(300A,0623) LO RadiationDoseInVivoMeasurementLabel 1 DICOM +(300A,0624) FD RadiationDoseCentralAxisDisplacement 2 DICOM +(300A,0625) FD RadiationDoseValue 1 DICOM +(300A,0626) FD RadiationDoseSourceToSkinDistance 1 DICOM +(300A,0627) FD RadiationDoseMeasurementPointCoordinates 3 DICOM +(300A,0628) FD RadiationDoseSourceToExternalContourDistance 1 DICOM +(300A,0629) SQ RTToleranceSetSequence 1 DICOM +(300A,062A) LO RTToleranceSetLabel 1 DICOM +(300A,062B) SQ AttributeToleranceValuesSequence 1 DICOM +(300A,062C) FD ToleranceValue 1 DICOM +(300A,062D) SQ PatientSupportPositionToleranceSequence 1 DICOM +(300A,062E) FD TreatmentTimeLimit 1 DICOM +(300A,062F) SQ CArmPhotonElectronControlPointSequence 1 DICOM +(300A,0630) SQ ReferencedRTRadiationSequence 1 DICOM +(300A,0631) SQ ReferencedRTInstanceSequence 1 DICOM +(300A,0632) SQ ReferencedRTPatientSetupSequence 1 DICOM +(300A,0634) FD SourceToPatientSurfaceDistance 1 DICOM +(300A,0635) SQ TreatmentMachineSpecialModeCodeSequence 1 DICOM +(300A,0636) US IntendedNumberOfFractions 1 DICOM +(300A,0637) CS RTRadiationSetIntent 1 DICOM +(300A,0638) CS RTRadiationPhysicalAndGeometricContentDetailFlag 1 DICOM +(300A,0639) CS RTRecordFlag 1 DICOM +(300A,063A) SQ TreatmentDeviceIdentificationSequence 1 DICOM +(300A,063B) SQ ReferencedRTPhysicianIntentSequence 1 DICOM +(300A,063C) FD CumulativeMeterset 1 DICOM +(300A,063D) FD DeliveryRate 1 DICOM +(300A,063E) SQ DeliveryRateUnitSequence 1 DICOM +(300A,063F) SQ TreatmentPositionSequence 1 DICOM +(300A,0640) FD RadiationSourceAxisDistance 1 DICOM +(300A,0641) US NumberOfRTBeamLimitingDevices 1 DICOM +(300A,0642) FD RTBeamLimitingDeviceProximalDistance 1 DICOM +(300A,0643) FD RTBeamLimitingDeviceDistalDistance 1 DICOM +(300A,0644) SQ ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence 1 DICOM +(300A,0645) FD BeamModifierOrientationAngle 1 DICOM +(300A,0646) SQ FixedRTBeamDelimiterDeviceSequence 1 DICOM +(300A,0647) SQ ParallelRTBeamDelimiterDeviceSequence 1 DICOM +(300A,0648) US NumberOfParallelRTBeamDelimiters 1 DICOM +(300A,0649) FD ParallelRTBeamDelimiterBoundaries 2-n DICOM +(300A,064A) FD ParallelRTBeamDelimiterPositions 2-n DICOM +(300A,064B) FD RTBeamLimitingDeviceOffset 2 DICOM +(300A,064C) SQ RTBeamDelimiterGeometrySequence 1 DICOM +(300A,064D) SQ RTBeamLimitingDeviceDefinitionSequence 1 DICOM +(300A,064E) CS ParallelRTBeamDelimiterOpeningMode 1 DICOM +(300A,064F) CS ParallelRTBeamDelimiterLeafMountingSide 1-n DICOM +(300A,0650) UI PatientSetupUID 1 DICOM +(300A,0651) SQ WedgeDefinitionSequence 1 DICOM +(300A,0652) FD RadiationBeamWedgeAngle 1 DICOM +(300A,0653) FD RadiationBeamWedgeThinEdgeDistance 1 DICOM +(300A,0654) FD RadiationBeamEffectiveWedgeAngle 1 DICOM +(300A,0655) US NumberOfWedgePositions 1 DICOM +(300A,0656) SQ RTBeamLimitingDeviceOpeningSequence 1 DICOM +(300A,0657) US NumberOfRTBeamLimitingDeviceOpenings 1 DICOM +(300A,0658) SQ RadiationDosimeterUnitSequence 1 DICOM +(300A,0659) SQ RTDeviceDistanceReferenceLocationCodeSequence 1 DICOM +(300A,065A) SQ RadiationDeviceConfigurationAndCommissioningKeySequence 1 DICOM +(300A,065B) SQ PatientSupportPositionParameterSequence 1 DICOM +(300A,065C) CS PatientSupportPositionSpecificationMethod 1 DICOM +(300A,065D) SQ PatientSupportPositionDeviceParameterSequence 1 DICOM +(300A,065E) US DeviceOrderIndex 1 DICOM +(300A,065F) US PatientSupportPositionParameterOrderIndex 1 DICOM +(300A,0660) SQ PatientSupportPositionDeviceToleranceSequence 1 DICOM +(300A,0661) US PatientSupportPositionToleranceOrderIndex 1 DICOM +(300A,0662) SQ CompensatorDefinitionSequence 1 DICOM +(300A,0663) CS CompensatorMapOrientation 1 DICOM +(300A,0664) OF CompensatorProximalThicknessMap 1 DICOM +(300A,0665) OF CompensatorDistalThicknessMap 1 DICOM +(300A,0666) FD CompensatorBasePlaneOffset 1 DICOM +(300A,0667) SQ CompensatorShapeFabricationCodeSequence 1 DICOM +(300A,0668) SQ CompensatorShapeSequence 1 DICOM +(300A,0669) FD RadiationBeamCompensatorMillingToolDiameter 1 DICOM +(300A,066A) SQ BlockDefinitionSequence 1 DICOM +(300A,066B) OF BlockEdgeData 1 DICOM +(300A,066C) CS BlockOrientation 1 DICOM +(300A,066D) FD RadiationBeamBlockThickness 1 DICOM +(300A,066E) FD RadiationBeamBlockSlabThickness 1 DICOM +(300A,066F) SQ BlockEdgeDataSequence 1 DICOM +(300A,0670) US NumberOfRTAccessoryHolders 1 DICOM +(300A,0671) SQ GeneralAccessoryDefinitionSequence 1 DICOM +(300A,0672) US NumberOfGeneralAccessories 1 DICOM +(300A,0673) SQ BolusDefinitionSequence 1 DICOM +(300A,0674) US NumberOfBoluses 1 DICOM +(300A,0675) UI EquipmentFrameOfReferenceUID 1 DICOM +(300A,0676) ST EquipmentFrameOfReferenceDescription 1 DICOM +(300A,0677) SQ EquipmentReferencePointCoordinatesSequence 1 DICOM +(300A,0678) SQ EquipmentReferencePointCodeSequence 1 DICOM +(300A,0679) FD RTBeamLimitingDeviceAngle 1 DICOM +(300A,067A) FD SourceRollAngle 1 DICOM +(300A,067B) SQ RadiationGenerationModeSequence 1 DICOM +(300A,067C) SH RadiationGenerationModeLabel 1 DICOM +(300A,067D) ST RadiationGenerationModeDescription 1 DICOM +(300A,067E) SQ RadiationGenerationModeMachineCodeSequence 1 DICOM +(300A,067F) SQ RadiationTypeCodeSequence 1 DICOM +(300A,0680) DS NominalEnergy 1 DICOM +(300A,0681) DS MinimumNominalEnergy 1 DICOM +(300A,0682) DS MaximumNominalEnergy 1 DICOM +(300A,0683) SQ RadiationFluenceModifierCodeSequence 1 DICOM +(300A,0684) SQ EnergyUnitCodeSequence 1 DICOM +(300A,0685) US NumberOfRadiationGenerationModes 1 DICOM +(300A,0686) SQ PatientSupportDevicesSequence 1 DICOM +(300A,0687) US NumberOfPatientSupportDevices 1 DICOM +(300A,0688) FD RTBeamModifierDefinitionDistance 1 DICOM +(300A,0689) SQ BeamAreaLimitSequence 1 DICOM +(300A,068A) SQ ReferencedRTPrescriptionSequence 1 DICOM +(300A,0700) UI TreatmentSessionUID 1 DICOM +(300A,0701) CS RTRadiationUsage 1 DICOM +(300A,0702) SQ ReferencedRTRadiationSetSequence 1 DICOM +(300A,0703) SQ ReferencedRTRadiationRecordSequence 1 DICOM +(300A,0704) US RTRadiationSetDeliveryNumber 1 DICOM +(300A,0705) US ClinicalFractionNumber 1 DICOM +(300A,0706) CS RTTreatmentFractionCompletionStatus 1 DICOM +(300A,0707) CS RTRadiationSetUsage 1 DICOM +(300A,0708) CS TreatmentDeliveryContinuationFlag 1 DICOM +(300A,0709) CS TreatmentRecordContentOrigin 1 DICOM +(300A,0714) CS RTTreatmentTerminationStatus 1 DICOM +(300A,0715) SQ RTTreatmentTerminationReasonCodeSequence 1 DICOM +(300A,0716) SQ MachineSpecificTreatmentTerminationCodeSequence 1 DICOM +(300A,0722) SQ RTRadiationSalvageRecordControlPointSequence 1 DICOM +(300A,0723) CS StartingMetersetValueKnownFlag 1 DICOM +(300A,0730) ST TreatmentTerminationDescription 1 DICOM +(300A,0731) SQ TreatmentToleranceViolationSequence 1 DICOM +(300A,0732) CS TreatmentToleranceViolationCategory 1 DICOM +(300A,0733) SQ TreatmentToleranceViolationAttributeSequence 1 DICOM +(300A,0734) ST TreatmentToleranceViolationDescription 1 DICOM +(300A,0735) ST TreatmentToleranceViolationIdentification 1 DICOM +(300A,0736) DT TreatmentToleranceViolationDateTime 1 DICOM +(300A,073A) DT RecordedRTControlPointDateTime 1 DICOM +(300A,073B) US ReferencedRadiationRTControlPointIndex 1 DICOM +(300A,073E) SQ AlternateValueSequence 1 DICOM +(300A,073F) SQ ConfirmationSequence 1 DICOM +(300A,0740) SQ InterlockSequence 1 DICOM +(300A,0741) DT InterlockDateTime 1 DICOM +(300A,0742) ST InterlockDescription 1 DICOM +(300A,0743) SQ InterlockOriginatingDeviceSequence 1 DICOM +(300A,0744) SQ InterlockCodeSequence 1 DICOM +(300A,0745) SQ InterlockResolutionCodeSequence 1 DICOM +(300A,0746) SQ InterlockResolutionUserSequence 1 DICOM +(300A,0760) DT OverrideDateTime 1 DICOM +(300A,0761) SQ TreatmentToleranceViolationTypeCodeSequence 1 DICOM +(300A,0762) SQ TreatmentToleranceViolationCauseCodeSequence 1 DICOM +(300A,0772) SQ MeasuredMetersetToDoseMappingSequence 1 DICOM +(300A,0773) US ReferencedExpectedInVivoMeasurementValueIndex 1 DICOM +(300A,0774) SQ DoseMeasurementDeviceCodeSequence 1 DICOM +(300A,0780) SQ AdditionalParameterRecordingInstanceSequence 1 DICOM +(300A,0783) ST InterlockOriginDescription 1 DICOM (300C,0002) SQ ReferencedRTPlanSequence 1 DICOM (300C,0004) SQ ReferencedBeamSequence 1 DICOM (300C,0006) IS ReferencedBeamNumber 1 DICOM @@ -4007,6 +4249,7 @@ (3010,002C) SQ SegmentAnnotationTypeCodeSequence 1 DICOM (3010,002D) LO DeviceLabel 1 DICOM (3010,002E) SQ DeviceTypeCodeSequence 1 DICOM +(3010,002F) SQ SegmentAnnotationTypeModifierCodeSequence 1 DICOM (3010,0030) SQ PatientEquipmentRelationshipCodeSequence 1 DICOM (3010,0031) UI ReferencedFiducialsUID 1 DICOM (3010,0032) SQ PatientTreatmentOrientationSequence 1 DICOM @@ -4095,6 +4338,18 @@ (3010,0086) LT IntendedStartDayOfWeek 1 DICOM (3010,0087) SQ WeekdayFractionPatternSequence 1 DICOM (3010,0088) SQ DeliveryTimeStructureCodeSequence 1 DICOM +(3010,0089) SQ TreatmentSiteModifierCodeSequence 1 DICOM +(3010,0090) CS RoboticBaseLocationIndicator 1 DICOM +(3010,0091) SQ RoboticPathNodeSetCodeSequence 1 DICOM +(3010,0092) UL RoboticNodeIdentifier 1 DICOM +(3010,0093) FD RTTreatmentSourceCoordinates 3 DICOM +(3010,0094) FD RadiationSourceCoordinateSystemYawAngle 1 DICOM +(3010,0095) FD RadiationSourceCoordinateSystemRollAngle 1 DICOM +(3010,0096) FD RadiationSourceCoordinateSystemPitchAngle 1 DICOM +(3010,0097) SQ RoboticPathControlPointSequence 1 DICOM +(3010,0098) SQ TomotherapeuticControlPointSequence 1 DICOM +(3010,0099) FD TomotherapeuticLeafOpenDurations 1-n DICOM +(3010,009A) FD TomotherapeuticLeafInitialClosedDurations 1-n DICOM (4010,0001) CS LowEnergyDetectors 1 DICOM/DICOS (4010,0002) CS HighEnergyDetectors 1 DICOM/DICOS (4010,0004) SQ DetectorGeometrySequence 1 DICOM/DICOS @@ -4130,7 +4385,7 @@ (4010,1026) DT RouteSegmentEndTime 1 DICOM/DICOS (4010,1027) CS TDRType 1 DICOM/DICOS (4010,1028) CS InternationalRouteSegment 1 DICOM/DICOS -(4010,1029) LO ThreatDetectionAlgorithmandVersion 1-n DICOM/DICOS +(4010,1029) LO ThreatDetectionAlgorithmAndVersion 1-n DICOM/DICOS (4010,102A) SH AssignedLocation 1 DICOM/DICOS (4010,102B) DT AlarmDecisionTime 1 DICOM/DICOS (4010,1031) CS AlarmDecision 1 DICOM/DICOS @@ -4213,7 +4468,7 @@ (7FE0,0002) OV ExtendedOffsetTableLengths 1 DICOM (7FE0,0008) OF FloatPixelData 1 DICOM (7FE0,0009) OD DoubleFloatPixelData 1 DICOM -(7FE0,0010) ox PixelData 1 DICOM +(7FE0,0010) px PixelData 1 DICOM (FFFA,FFFA) SQ DigitalSignaturesSequence 1 DICOM (FFFC,FFFC) OB DataSetTrailingPadding 1 DICOM (FFFE,E000) na Item 1 DICOM @@ -4602,6 +4857,7 @@ (3006,00C0) SQ RETIRED_FrameOfReferenceRelationshipSequence 1 DICOM/retired (3006,00C2) UI RETIRED_RelatedFrameOfReferenceUID 1 DICOM/retired (3006,00C4) CS RETIRED_FrameOfReferenceTransformationType 1 DICOM/retired +(300A,0082) DS RETIRED_BeamDoseSpecificationPoint 3 DICOM/retired (300A,008D) FL RETIRED_AverageBeamDosePointDepth 1 DICOM/retired (300A,008E) FL RETIRED_AverageBeamDosePointEquivalentDepth 1 DICOM/retired (300A,008F) FL RETIRED_AverageBeamDosePointSSD 1 DICOM/retired @@ -4696,161 +4952,6 @@ # #--------------------------------------------------------------------------- # -# Supplement 175 (Second Generation Radiotherapy - C-Arm RT Treatment Modalities) -# -(0018,100B) UI ManufacturerDeviceClassUID 1-n DICOM/Supplement_175 -(0018,1630) CS OutlineShapeType 1 DICOM/Supplement_175 -(0018,1631) FD OutlineLeftVerticalEdge 1 DICOM/Supplement_175 -(0018,1632) FD OutlineRightVerticalEdge 1 DICOM/Supplement_175 -(0018,1633) FD OutlineUpperHorizontalEdge 1 DICOM/Supplement_175 -(0018,1634) FD OutlineLowerHorizontalEdge 1 DICOM/Supplement_175 -(0018,1635) FD CenterOfCircularOutline 2 DICOM/Supplement_175 -(0018,1636) FD DiameterOfCircularOutline 1 DICOM/Supplement_175 -(0018,1637) UL NumberOfPolygonalVertices 1 DICOM/Supplement_175 -(0018,1638) OF VerticesOfThePolygonalOutline 1 DICOM/Supplement_175 -(3006,00C9) SQ PatientLocationCoordinatesSequence 1 DICOM/Supplement_175 -(3006,00CA) SQ PatientLocationCoordinatesCodeSequence 1 DICOM/Supplement_175 -(3006,00CB) SQ PatientSupportPositionSequence 1 DICOM/Supplement_175 -(300A,0600) US RTControlPointIndex 1 DICOM/Supplement_175 -(300A,0601) US RadiationGenerationModeIndex 1 DICOM/Supplement_175 -(300A,0602) US ReferencedDefinedDeviceIndex 1 DICOM/Supplement_175 -(300A,0603) US RadiationDoseIdentificationIndex 1 DICOM/Supplement_175 -(300A,0604) US NumberOfRTControlPoints 1 DICOM/Supplement_175 -(300A,0605) US ReferencedRadiationGenerationModeIndex 1 DICOM/Supplement_175 -(300A,0606) US TreatmentPositionIndex 1 DICOM/Supplement_175 -(300A,0607) US ReferencedDeviceIndex 1 DICOM/Supplement_175 -(300A,0608) LO TreatmentPositionGroupLabel 1 DICOM/Supplement_175 -(300A,0609) UI TreatmentPositionGroupUID 1 DICOM/Supplement_175 -(300A,060A) SQ TreatmentPositionGroupSequence 1 DICOM/Supplement_175 -(300A,060B) US ReferencedTreatmentPositionIndex 1 DICOM/Supplement_175 -(300A,060C) US ReferencedRadiationDoseIdentificationIndex 1 DICOM/Supplement_175 -(300A,060D) FD RTAccessoryHolderWaterEquivalentThickness 1 DICOM/Supplement_175 -(300A,060E) US ReferencedRTAccessoryHolderDeviceIndex 1 DICOM/Supplement_175 -(300A,060F) CS RTAccessoryHolderSlotExistenceFlag 1 DICOM/Supplement_175 -(300A,0610) SQ RTAccessoryHolderSlotSequence 1 DICOM/Supplement_175 -(300A,0611) LO RTAccessoryHolderSlotID 1 DICOM/Supplement_175 -(300A,0612) FD RTAccessoryHolderSlotDistance 1 DICOM/Supplement_175 -(300A,0613) FD RTAccessorySlotDistance 1 DICOM/Supplement_175 -(300A,0614) SQ RTAccessoryHolderDefinitionSequence 1 DICOM/Supplement_175 -(300A,0615) LO RTAccessoryDeviceSlotID 1 DICOM/Supplement_175 -(300A,0616) SQ RTRadiationSequence 1 DICOM/Supplement_175 -(300A,0617) SQ RadiationDoseSequence 1 DICOM/Supplement_175 -(300A,0618) SQ RadiationDoseIdentificationSequence 1 DICOM/Supplement_175 -(300A,0619) LO RadiationDoseIdentificationLabel 1 DICOM/Supplement_175 -(300A,061A) CS ReferenceDoseType 1 DICOM/Supplement_175 -(300A,061B) CS PrimaryDoseValueIndicator 1 DICOM/Supplement_175 -(300A,061C) SQ DoseValuesSequence 1 DICOM/Supplement_175 -(300A,061D) CS DoseValuePurpose 1-n DICOM/Supplement_175 -(300A,061E) FD ReferenceDosePointCoordinates 3 DICOM/Supplement_175 -(300A,061F) SQ RadiationDoseValuesParametersSequence 1 DICOM/Supplement_175 -(300A,0620) SQ MetersetToDoseMappingSequence 1 DICOM/Supplement_175 -(300A,0621) SQ ExpectedInVivoMeasurementValuesSequence 1 DICOM/Supplement_175 -(300A,0622) US ExpectedInVivoMeasurementValueIndex 1 DICOM/Supplement_175 -(300A,0623) LO RadiationDoseInVivoMeasurementLabel 1 DICOM/Supplement_175 -(300A,0624) FD RadiationDoseCentralAxisDisplacement 2 DICOM/Supplement_175 -(300A,0625) FD RadiationDoseValue 1 DICOM/Supplement_175 -(300A,0626) FD RadiationDoseSourceToSkinDistance 1 DICOM/Supplement_175 -(300A,0627) FD RadiationDoseMeasurementPointCoordinates 3 DICOM/Supplement_175 -(300A,0628) FD RadiationDoseSourceToExternalContourDistance 1 DICOM/Supplement_175 -(300A,0629) SQ RTToleranceSetSequence 1 DICOM/Supplement_175 -(300A,062A) LO RTToleranceSetLabel 1 DICOM/Supplement_175 -(300A,062B) SQ AttributeToleranceValuesSequence 1 DICOM/Supplement_175 -(300A,062C) FD ToleranceValue 1 DICOM/Supplement_175 -(300A,062D) SQ PatientSupportPositionToleranceSequence 1 DICOM/Supplement_175 -(300A,062E) FD TreatmentTimeLimit 1 DICOM/Supplement_175 -(300A,062F) SQ CArmPhotonElectronControlPointSequence 1 DICOM/Supplement_175 -(300A,0630) SQ ReferencedRTRadiationSequence 1 DICOM/Supplement_175 -(300A,0631) SQ ReferencedRTInstanceSequence 1 DICOM/Supplement_175 -(300A,0632) SQ ReferencedRTPatientSetupSequence 1 DICOM/Supplement_175 -(300A,0634) FD SourceToPatientSurfaceDistance 1 DICOM/Supplement_175 -(300A,0635) SQ TreatmentMachineSpecialModeCodeSequence 1 DICOM/Supplement_175 -(300A,0636) US IntendedNumberOfFractions 1 DICOM/Supplement_175 -(300A,0637) CS RTRadiationSetIntent 1 DICOM/Supplement_175 -(300A,0638) CS RTRadiationPhysicalAndGeometricContentDetailFlag 1 DICOM/Supplement_175 -(300A,0639) CS RTRecordFlag 1 DICOM/Supplement_175 -(300A,063A) SQ TreatmentDeviceIdentificationSequence 1 DICOM/Supplement_175 -(300A,063B) SQ ReferencedRTPhysicianIntentSequence 1 DICOM/Supplement_175 -(300A,063C) FD CumulativeMeterset 1 DICOM/Supplement_175 -(300A,063D) FD DeliveryRate 1 DICOM/Supplement_175 -(300A,063E) SQ DeliveryRateUnitSequence 1 DICOM/Supplement_175 -(300A,063F) SQ TreatmentPositionSequence 1 DICOM/Supplement_175 -(300A,0640) FD RadiationSourceAxisDistance 1 DICOM/Supplement_175 -(300A,0641) US NumberOfRTBeamLimitingDevices 1 DICOM/Supplement_175 -(300A,0642) FD RTBeamLimitingDeviceProximalDistance 1 DICOM/Supplement_175 -(300A,0643) FD RTBeamLimitingDeviceDistalDistance 1 DICOM/Supplement_175 -(300A,0644) SQ ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence 1 DICOM/Supplement_175 -(300A,0645) FD BeamsModifierOrientationAngle 1 DICOM/Supplement_175 -(300A,0646) SQ FixedRTBeamDelimiterDeviceSequence 1 DICOM/Supplement_175 -(300A,0647) SQ ParallelRTBeamDelimiterDeviceSequence 1 DICOM/Supplement_175 -(300A,0648) US NumberOfParallelRTBeamDelimiters 1 DICOM/Supplement_175 -(300A,0649) FD ParallelRTBeamDelimiterBoundaries 2-n DICOM/Supplement_175 -(300A,064A) FD ParallelRTBeamDelimiterPositions 2-n DICOM/Supplement_175 -(300A,064B) FD RTBeamLimitingDeviceOffset 2 DICOM/Supplement_175 -(300A,064C) SQ RTBeamDelimiterGeometrySequence 1 DICOM/Supplement_175 -(300A,064D) SQ RTBeamLimitingDeviceDefinitionSequence 1 DICOM/Supplement_175 -(300A,064E) CS ParallelRTBeamDelimiterOpeningMode 1 DICOM/Supplement_175 -(300A,064F) CS ParallelRTBeamDelimiterLeafMountingSide 1-n DICOM/Supplement_175 -(300A,0650) UI PatientSetupUID 1 DICOM/Supplement_175 -(300A,0651) SQ WedgeDefinitionSequence 1 DICOM/Supplement_175 -(300A,0652) FD RadiationBeamWedgeAngle 1 DICOM/Supplement_175 -(300A,0653) FD RadiationBeamWedgeThinEdgeDistance 1 DICOM/Supplement_175 -(300A,0654) FD RadiationBeamEffectiveWedgeAngle 1 DICOM/Supplement_175 -(300A,0655) US NumberOfWedgePositions 1 DICOM/Supplement_175 -(300A,0656) SQ RTBeamLimitingDeviceOpeningSequence 1 DICOM/Supplement_175 -(300A,0657) US NumberOfRTBeamLimitingDeviceOpenings 1 DICOM/Supplement_175 -(300A,0658) SQ RadiationDosimeterUnitSequence 1 DICOM/Supplement_175 -(300A,0659) SQ RTDeviceDistanceReferenceLocationCodeSequence 1 DICOM/Supplement_175 -(300A,065A) SQ RadiationDeviceConfigurationAndCommissioningKeySequence 1 DICOM/Supplement_175 -(300A,065B) SQ PatientSupportPositionParameterSequence 1 DICOM/Supplement_175 -(300A,065C) CS PatientSupportPositionSpecificationMethod 1 DICOM/Supplement_175 -(300A,065D) SQ PatientSupportPositionDeviceParameterSequence 1 DICOM/Supplement_175 -(300A,065E) US DeviceOrderIndex 1 DICOM/Supplement_175 -(300A,065F) US PatientSupportPositionParameterOrderIndex 1 DICOM/Supplement_175 -(300A,0660) SQ PatientSupportPositionDeviceToleranceSequence 1 DICOM/Supplement_175 -(300A,0661) US PatientSupportPositionToleranceOrderIndex 1 DICOM/Supplement_175 -(300A,0662) SQ CompensatorDefinitionSequence 1 DICOM/Supplement_175 -(300A,0663) CS CompensatorMapOrientation 1 DICOM/Supplement_175 -(300A,0664) OF CompensatorProximalThicknessMap 1 DICOM/Supplement_175 -(300A,0665) OF CompensatorDistalThicknessMap 1 DICOM/Supplement_175 -(300A,0666) FD CompensatorBasePlaneOffset 1 DICOM/Supplement_175 -(300A,0667) SQ CompensatorShapeFabricationCodeSequence 1 DICOM/Supplement_175 -(300A,0668) SQ CompensatorShapeSequence 1 DICOM/Supplement_175 -(300A,0669) FD RadiationBeamCompensatorMillingToolDiameter 1 DICOM/Supplement_175 -(300A,066A) SQ BlockDefinitionSequence 1 DICOM/Supplement_175 -(300A,066B) OF BlockEdgeData 1 DICOM/Supplement_175 -(300A,066C) CS BlockOrientation 1 DICOM/Supplement_175 -(300A,066D) FD RadiationBeamBlockThickness 1 DICOM/Supplement_175 -(300A,066E) FD RadiationBeamBlockSlabThickness 1 DICOM/Supplement_175 -(300A,066F) SQ BlockEdgeDataSequence 1 DICOM/Supplement_175 -(300A,0670) US NumberOfRTAccessoryHolders 1 DICOM/Supplement_175 -(300A,0671) SQ GeneralAccessoryDefinitionSequence 1 DICOM/Supplement_175 -(300A,0672) US NumberOfGeneralAccessories 1 DICOM/Supplement_175 -(300A,0673) SQ BolusDefinitionSequence 1 DICOM/Supplement_175 -(300A,0674) US NumberOfBoluses 1 DICOM/Supplement_175 -(300A,0675) UI EquipmentFrameOfReferenceUID 1 DICOM/Supplement_175 -(300A,0676) ST EquipmentFrameOfReferenceDescription 1 DICOM/Supplement_175 -(300A,0677) SQ EquipmentReferencePointCoordinatesSequence 1 DICOM/Supplement_175 -(300A,0678) SQ EquipmentReferencePointCodeSequence 1 DICOM/Supplement_175 -(300A,0679) FD RTBeamLimitingDeviceAngle 1 DICOM/Supplement_175 -(300A,067A) FD SourceRollAngle 1 DICOM/Supplement_175 -(300A,067B) SQ RadiationGenerationModeSequence 1 DICOM/Supplement_175 -(300A,067C) SH RadiationGenerationModeLabel 1 DICOM/Supplement_175 -(300A,067D) ST RadiationGenerationModeDescription 1 DICOM/Supplement_175 -(300A,067E) SQ RadiationGenerationModeMachineCodeSequence 1 DICOM/Supplement_175 -(300A,067F) SQ RadiationTypeCodeSequence 1 DICOM/Supplement_175 -(300A,0680) DS NominalEnergy 1 DICOM/Supplement_175 -(300A,0681) DS MinimumNominalEnergy 1 DICOM/Supplement_175 -(300A,0682) DS MaximumNominalEnergy 1 DICOM/Supplement_175 -(300A,0683) SQ RadiationFluenceModifierCodeSequence 1 DICOM/Supplement_175 -(300A,0684) SQ EnergyUnitCodeSequence 1 DICOM/Supplement_175 -(300A,0685) US NumberOfRadiationGenerationModes 1 DICOM/Supplement_175 -(300A,0686) SQ PatientSupportDevicesSequence 1 DICOM/Supplement_175 -(300A,0687) US NumberOfPatientSupportDevices 1 DICOM/Supplement_175 -(300A,0688) FD RTBeamModifierDefinitionDistance 1 DICOM/Supplement_175 -(300A,0689) SQ BeamAreaLimitSequence 1 DICOM/Supplement_175 -# -#--------------------------------------------------------------------------- -# # Private Creator Data Elements # (0009-o-FFFF,0000) UL PrivateGroupLength 1 PRIVATE diff --git a/dcmdata/data/private.dic b/dcmdata/data/private.dic index b754dc78..bd613504 100644 --- a/dcmdata/data/private.dic +++ b/dcmdata/data/private.dic @@ -1,5 +1,5 @@ # -# Copyright (C) 1994-2013, OFFIS e.V. +# Copyright (C) 1994-2020, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by @@ -26,6 +26,7 @@ # - Circle Cardiovascular Imaging cmr42 3.0 conformance statement # - David Clunie's dicom3tools package, 2002-04-20 snapshot # - Fuji CR console, 3rd release +# - GE Vivid S70 version 201 conformance statement # - Intelerad Medical Systems Inc., Image Server # - OCULUS Pentacam 1.17 conformance statement # - Philips Digital Diagnost 1.3 conformance statement @@ -1044,6 +1045,8 @@ (0023,"GEMS_STDY_01",74) SL NumberOfUpdatesToHeader 1 PrivateTag (0023,"GEMS_STDY_01",7d) SS IndicatesIfStudyHasCompleteInfo 1 PrivateTag +(7fe1,"GEMS_Ultrasound_MovieGroup_001",1060) px IllegalPrivatePixelSequence 1 PrivateTag + (0033,"GEMS_YMHD_01",05) UN Unknown 1 PrivateTag (0033,"GEMS_YMHD_01",06) UN Unknown 1 PrivateTag diff --git a/dcmdata/docs/cda2dcm.man b/dcmdata/docs/cda2dcm.man index 3cc31a45..0a970ea8 100644 --- a/dcmdata/docs/cda2dcm.man +++ b/dcmdata/docs/cda2dcm.man @@ -169,6 +169,30 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes \endverbatim +\section cda2dcm_notes NOTES + +\subsection cda2dcm_attribute_sources Attribute Sources + +The application may be fed with some additional input for filling mandatory (and +optional) attributes in the new DICOM file like patient, study and series +information: + +\li The \e --key option can be used to add further attributes to the DICOM + output file. + +\li It is also possible to specify sequences, items and nested + attributes using the \e --key option. In these cases, a special "path" + notation has to be used. Details on this path notation can be found in the + documentation of \b dcmodify. + +\li The \e --key option can be present more than once. + +\li The value part (after the '=') may be absent causing the attribute to be + set with zero length. + +\li Please be advised that the \e --key option is applied at the very end, just + before saving the DICOM file, so there is no value checking whatsoever. + \section cda2dcm_logging LOGGING The level of logging output of the various command line tools and underlying @@ -253,6 +277,6 @@ It is an error if no data dictionary can be loaded. \section cda2dcm_copyright COPYRIGHT -Copyright (C) 2018 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2018-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/dcm2json.man b/dcmdata/docs/dcm2json.man index f432b05e..c202d2a8 100644 --- a/dcmdata/docs/dcm2json.man +++ b/dcmdata/docs/dcm2json.man @@ -19,7 +19,7 @@ raw data set) to JSON (JavaScript Object Notation). The output refers to the "DICOM JSON Model", which is found in DICOM Part 18 Section F. If \b dcm2json reads a raw data set (DICOM data without a file format -meta-header) it will attempt to guess the transfer syntax by examining the +meta-header), it will attempt to guess the transfer syntax by examining the first few bytes of the file. It is not always possible to correctly guess the transfer syntax and it is better to convert a data set to a file format whenever possible (using the \b dcmconv utility). It is also possible to use @@ -38,79 +38,89 @@ jsonfile-out JSON output filename (default: stdout) \subsection dcm2json_general_options general options \verbatim - -h --help - print this help text and exit + -h --help + print this help text and exit - --version - print version information and exit + --version + print version information and exit - --arguments - print expanded command line arguments + --arguments + print expanded command line arguments - -q --quiet - quiet mode, print no warnings and errors + -q --quiet + quiet mode, print no warnings and errors - -v --verbose - verbose mode, print processing details + -v --verbose + verbose mode, print processing details - -d --debug - debug mode, print debug information + -d --debug + debug mode, print debug information - -ll --log-level [l]evel: string constant - (fatal, error, warn, info, debug, trace) - use level l for the logger + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger - -lc --log-config [f]ilename: string - use config file f for the logger + -lc --log-config [f]ilename: string + use config file f for the logger \endverbatim \subsection dcm2json_input_options input options \verbatim input file format: - +f --read-file - read file format or data set (default) + +f --read-file + read file format or data set (default) - +fo --read-file-only - read file format only + +fo --read-file-only + read file format only - -f --read-dataset - read data set without file meta information + -f --read-dataset + read data set without file meta information input transfer syntax: - -t= --read-xfer-auto - use TS recognition (default) + -t= --read-xfer-auto + use TS recognition (default) - -td --read-xfer-detect - ignore TS specified in the file meta header + -td --read-xfer-detect + ignore TS specified in the file meta header - -te --read-xfer-little - read with explicit VR little endian TS + -te --read-xfer-little + read with explicit VR little endian TS - -tb --read-xfer-big - read with explicit VR big endian TS + -tb --read-xfer-big + read with explicit VR big endian TS - -ti --read-xfer-implicit - read with implicit VR little endian TS + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection dcm2json_processing_options processing options +\verbatim +encoding of infinity and not-a-number: + -es --encode-strict + report error for 'inf' and 'nan' (default) + + -ee --encode-extended + permit 'inf' and 'nan' in JSON numbers \endverbatim \subsection dcm2json_output_options output options \verbatim output format: - +fc --formatted-code - enable whitespace formatting (default) + +fc --formatted-code + enable whitespace formatting (default) - # prints additional spaces and newlines for increased - # readability + # prints additional spaces and newlines for increased + # readability - -fc --compact-code - print only required characters + -fc --compact-code + print only required characters - +m --write-meta - write data set with meta information - (warning: not conforming to the DICOM standard) + +m --write-meta + write data set with meta information + (warning: not conforming to the DICOM standard) \endverbatim \section dcm2json_json_format JSON Format @@ -277,19 +287,20 @@ the following (see DICOM Part 18 Section F for details): \subsection dcm2json_bulk_data Bulk Data Binary data, i.e. DICOM element values with Value Representations (VR) of OB -or OW, as well as OD, OF and UN values are by default not written to the JSON -output because of their size. Instead, for each element, a new Universally -Unique Identifier (UUID) is being generated and written as an value of a -BulkDataURI JSON element. So far, there is no possibility to write an -additional file to hold the binary data for each of the binary data chunks. +or OW, as well as OD, OF, OL, OV and UN values are always written as +"InlineBinary" (base64 encoding) to the JSON output. A future version of this +tool might optionally use a "BulkDataURI" instead, i.e. the WADO-RS URL of a +bulk data item that contains the element value. This would be particularly +useful for large amounts of data, such as pixel data. \section dcm2json_notes NOTES \subsection dcm2json_character_encoding Character Encoding -\b dcm2json always tries to output in UTF-8 encoding. If this is not possible, -e.g. because there is no support for character set conversion, ASCII is used -instead (which is a subset of UTF-8). +As required by the DICOM JSON encoding, \b dcm2json always creates output in +Unicode UTF-8 encoding and converts DICOM datasets accordingly. If this is not +possible, for example because DCMTK has been compiled without either iconv or +ICU library, an error is returned. \section dcm2json_logging LOGGING @@ -332,6 +343,34 @@ allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \/dumppat.txt). +\section dcm2json_exit_codes EXIT CODES + +The \b dcm2json utility uses the following exit codes when terminating. This +enables the user to check for the reason why the application terminated. + +\subsection dcm2json_exit_codes_general general +\verbatim +EXITCODE_NO_ERROR 0 +EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 +\endverbatim + +\subsection dcm2json_exit_codes_input_file_errors input file errors +\verbatim +EXITCODE_CANNOT_READ_INPUT_FILE 20 +EXITCODE_NO_INPUT_FILES 21 +\endverbatim + +\subsection dcm2json_exit_codes_output_file_errors output file errors +\verbatim +EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 +\endverbatim + +\subsection dcm2json_exit_codes_processing_errors processing errors +\verbatim +EXITCODE_CANNOT_CONVERT_TO_UNICODE 80 +EXITCODE_CANNOT_WRITE_VALID_JSON 81 +\endverbatim + \section dcm2json_environment ENVIRONMENT The \b dcm2json utility will attempt to load DICOM data dictionaries specified @@ -350,6 +389,6 @@ It is an error if no data dictionary can be loaded. \section dcm2json_copyright COPYRIGHT -Copyright (C) 2016-2017 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2016-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/dcm2xml.man b/dcmdata/docs/dcm2xml.man index f2e58ec8..6ed33efb 100644 --- a/dcmdata/docs/dcm2xml.man +++ b/dcmdata/docs/dcm2xml.man @@ -213,7 +213,7 @@ looks like the following: - 256\\0\\8 + 256\0\8 ... @@ -261,7 +261,7 @@ standard, part 19 ("Application Hosting"). \subsection dcm2xml_bulk_data Bulk Data Binary data, i.e. DICOM element values with Value Representations (VR) of OB -or OW, as well as OD, OF, OV and UN values are by default not written to the +or OW, as well as OD, OF, OL, OV and UN values are by default not written to the XML output because of their size. Instead, for each element, a new Universally Unique Identifier (UUID) is being generated and written as an attribute of a \ XML element. So far, there is no possibility to write an @@ -273,17 +273,17 @@ available in future versions of \b dcm2xml. In addition, Supplement 163 (Store Over the Web by Representational State Transfer Services) introduces a new \ XML element that allows for encoding binary data as Base64. Currently, the command line option -\e --encode-base64 enables this encoding for the following VRs: OB, OD, OF, OV, -OW and UN. +\e --encode-base64 enables this encoding for the following VRs: OB, OD, OF, OL, +OV, OW and UN. \subsection dcm2xml_known_issues Known Issues In addition to what is written in the above section on "Bulk Data", there are further known issues with the current implementation of the Native DICOM Model -format. For example, large element values with a VR other than OB, OD, OF, OV, -OW or UN are currently never written as bulk data, although it might be useful, -e.g. for very long text elements (especially UT) or very long numeric fields -(of various VRs). +format. For example, large element values with a VR other than OB, OD, OF, OL, +OV, OW or UN are currently never written as bulk data, although it might be +useful, e.g. for very long text elements (especially UT) or very long numeric +fields (of various VRs). \section dcm2xml_notes NOTES @@ -391,6 +391,6 @@ It is an error if no data dictionary can be loaded. \section dcm2xml_copyright COPYRIGHT -Copyright (C) 2002-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2002-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/dcmconv.man b/dcmdata/docs/dcmconv.man index 3c947313..bb266eab 100644 --- a/dcmdata/docs/dcmconv.man +++ b/dcmdata/docs/dcmconv.man @@ -242,11 +242,11 @@ other processing options: \verbatim output file format: - +F --write-file - write file format (default) - +Fm --write-new-meta-info - write file format with new meta information + write file format with new meta information (default) + + +F --write-file + write file format -F --write-dataset write data set without file meta information @@ -387,6 +387,6 @@ It is an error if no data dictionary can be loaded. \section dcmconv_copyright COPYRIGHT -Copyright (C) 1994-2017 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1994-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/dcmodify.man b/dcmdata/docs/dcmodify.man index f8764314..69d74001 100644 --- a/dcmdata/docs/dcmodify.man +++ b/dcmdata/docs/dcmodify.man @@ -60,6 +60,9 @@ However, if specifying an item number like '5', all 6 items (counted from zero) can be (and are) automatically generated in insert mode. If already 2 items would exist, the rest (4) would be inserted. +\b dcmodify does not work on directories, i.e. the parameter \e dcmfile-in... +must not include directory names. + Please note that there are some issues concerning the modification of private tags (see PRIVATE TAGS section) and for changing UIDs (CHANGING UIDs section). @@ -362,6 +365,12 @@ When choosing the \e -gin option, the related metaheader tag ('Media Storage SOP Instance UID') is updated automatically. This behavior cannot be disabled. +When working on multiple input files, \b dcmodify processes each file +in isolated fashion, i.e. it will generate UIDs for each single file. For +example, when using the \e -gst option, \b dcmodify will insert a different +Study Instance UID into each file instead of generating a single one and +writing it to each file that is being processed. + \section dcmodify_creating_new_files CREATING NEW FILES Option \e --create-file lets \b dcmodify create a file if it does not already diff --git a/dcmdata/docs/dump2dcm.man b/dcmdata/docs/dump2dcm.man index b1ad195e..0029114f 100644 --- a/dcmdata/docs/dump2dcm.man +++ b/dcmdata/docs/dump2dcm.man @@ -199,13 +199,13 @@ VR: Value Representation must be written as 2 characters as in between the two characters. If the VR can be determined from the tag, this part of a line is optional. Value: There are several rules for writing values: - 1. US, SS, SL, UL, FD, FL, OD, OF and OL are written as decimal - strings that can be read by scanf(). + 1. US, SS, UL, SL, UV, SV, FD, FL, OD, OF, OL and OV are written + as decimal strings that can be read by scanf(). 2. AT is written as '(gggg,eeee)' with additional spaces stripped off automatically and gggg and eeee being decimal strings that can be read by scanf(). 3. OB and OW values are written as byte or word hexadecimal - values separated by '\\' character. Alternatively, OB or OW + values separated by '\' character. Alternatively, OB or OW values can be read from a separate file by writing the filename prefixed by a '=' character (e.g. '=largepix.dat'). The contents of the file will be read as is. By default, OW @@ -225,22 +225,24 @@ Value: There are several rules for writing values: line. Anything after the ']' is interpreted as comment. 7. '(' and '<' are interpreted special and may not be used when writing an input file by hand as beginning characters of a - string. Multiple Value are separated by '\\'. The lines + string. Multiple Value are separated by '\'. The lines need not be sorted into ascending tag order. References in DICOM Directories are not supported. Semantic errors are not detected. \endverbatim -\subsection dump2dcm_notes_example Example +\subsection dump2dcm_notes_examples Examples + +The following lines show valid examples of the syntax described above: \verbatim (0008,0020) DA [19921012] # 8, 1 StudyDate (0008,0016) UI =MRImageStorage # 26, 1 SOPClassUID (0002,0012) UI [1.2.276.0.7230010.100.1.1] - (0020,0032) DS [0.0\\0.0] # 8, 2 ImagePositionPatient + (0020,0032) DS [0.0\0.0] # 8, 2 ImagePositionPatient (0028,0009) AT (3004,000c) # 4, 1 FrameIncrementPointer (0028,0010) US 256 # 4, 1 Rows - (0002,0001) OB 01\\00 + (0002,0001) OB 01\00 \endverbatim \subsection dump2dcm_limitations Limitations @@ -312,6 +314,6 @@ It is an error if no data dictionary can be loaded. \section dump2dcm_copyright COPYRIGHT -Copyright (C) 1996-2016 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1996-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/img2dcm.man b/dcmdata/docs/img2dcm.man index 4c84e104..125b8749 100644 --- a/dcmdata/docs/img2dcm.man +++ b/dcmdata/docs/img2dcm.man @@ -246,11 +246,14 @@ order: enabled, no automatic attribute insertion will take place. \li The \e --key option can be used to add further attributes to the DICOM - output file. This option is applied at the very end, just before saving the - DICOM file. It is also possible to specify sequences, items and nested + output file. It is also possible to specify sequences, items and nested attributes using the \e --key option. In these cases, a special "path" notation has to be used. Details on this path notation can be found in the - documentation of \b dcmodify. + documentation of \b dcmodify. The \e --key option can be present more than + once. The value part (after the '=') may be absent causing the attribute to + be set with zero length. Please be advised that the \e --key option is + applied at the very end, just before saving the DICOM file, so there is no + value checking whatsoever. \subsection img2dcm_uids UIDs @@ -496,6 +499,6 @@ images \section img2dcm_copyright COPYRIGHT -Copyright (C) 2007-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2007-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/pdf2dcm.man b/dcmdata/docs/pdf2dcm.man index 282476d7..5451d207 100644 --- a/dcmdata/docs/pdf2dcm.man +++ b/dcmdata/docs/pdf2dcm.man @@ -159,6 +159,30 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes \endverbatim +\section pdf2dcm_notes NOTES + +\subsection pdf2dcm_attribute_sources Attribute Sources + +The application may be fed with some additional input for filling mandatory (and +optional) attributes in the new DICOM file like patient, study and series +information: + +\li The \e --key option can be used to add further attributes to the DICOM + output file. + +\li It is also possible to specify sequences, items and nested + attributes using the \e --key option. In these cases, a special "path" + notation has to be used. Details on this path notation can be found in the + documentation of \b dcmodify. + +\li The \e --key option can be present more than once. + +\li The value part (after the '=') may be absent causing the attribute to be + set with zero length. + +\li Please be advised that the \e --key option is applied at the very end, just + before saving the DICOM file, so there is no value checking whatsoever. + \section pdf2dcm_logging LOGGING The level of logging output of the various command line tools and underlying @@ -247,6 +271,6 @@ It is an error if no data dictionary can be loaded. \section pdf2dcm_copyright COPYRIGHT -Copyright (C) 2005-2018 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2005-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/stl2dcm.man b/dcmdata/docs/stl2dcm.man index e47a7c30..11571601 100644 --- a/dcmdata/docs/stl2dcm.man +++ b/dcmdata/docs/stl2dcm.man @@ -179,6 +179,30 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes \endverbatim +\section stl2dcm_notes NOTES + +\subsection stl2dcm_attribute_sources Attribute Sources + +The application may be fed with some additional input for filling mandatory (and +optional) attributes in the new DICOM file like patient, study and series +information: + +\li The \e --key option can be used to add further attributes to the DICOM + output file. + +\li It is also possible to specify sequences, items and nested + attributes using the \e --key option. In these cases, a special "path" + notation has to be used. Details on this path notation can be found in the + documentation of \b dcmodify. + +\li The \e --key option can be present more than once. + +\li The value part (after the '=') may be absent causing the attribute to be + set with zero length. + +\li Please be advised that the \e --key option is applied at the very end, just + before saving the DICOM file, so there is no value checking whatsoever. + \section stl2dcm_logging LOGGING The level of logging output of the various command line tools and underlying @@ -263,6 +287,6 @@ It is an error if no data dictionary can be loaded. \section stl2dcm_copyright COPYRIGHT -Copyright (C) 2018 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2018-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/docs/xml2dcm.man b/dcmdata/docs/xml2dcm.man index 02fea6cd..b48d870a 100644 --- a/dcmdata/docs/xml2dcm.man +++ b/dcmdata/docs/xml2dcm.man @@ -195,7 +195,7 @@ The basic structure of the XML input expected looks like the following: - 256\\0\\8 + 256\0\8 ... @@ -342,6 +342,6 @@ It is an error if no data dictionary can be loaded. \section xml2dcm_copyright COPYRIGHT -Copyright (C) 2003-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2003-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcbytstr.h b/dcmdata/include/dcmtk/dcmdata/dcbytstr.h index ca28195a..55712b93 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcbytstr.h +++ b/dcmdata/include/dcmtk/dcmdata/dcbytstr.h @@ -247,6 +247,14 @@ class DCMTK_DCMDATA_EXPORT DcmByteString: public DcmElement */ virtual OFCondition putString(const char *stringVal); + /** set element value at specific VM position in the given character string. + * @param stringVal input character string (possibly multi-valued) + * @param pos position (0..vm) where the value should be inserted + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putOFStringAtPos(const OFString& stringVal, + const unsigned long pos = 0); + /** set element value from the given character string. * The length of the string has to be specified explicitly. The string can, therefore, * also contain more than one NULL byte. diff --git a/dcmdata/include/dcmtk/dcmdata/dccodec.h b/dcmdata/include/dcmtk/dcmdata/dccodec.h index 60b5de50..5d991483 100644 --- a/dcmdata/include/dcmtk/dcmdata/dccodec.h +++ b/dcmdata/include/dcmtk/dcmdata/dccodec.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2018, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -92,6 +92,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -99,7 +103,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const = 0; + const DcmStack & objStack, + OFBool& removeOldRep) const = 0; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -149,6 +154,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -157,7 +166,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const = 0; + DcmStack & objStack, + OFBool& removeOldRep) const = 0; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -171,6 +181,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -180,7 +194,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const = 0; + DcmStack & objStack, + OFBool& removeOldRep) const = 0; /** checks if this codec is able to convert from the * given current transfer syntax to the given new @@ -345,6 +360,10 @@ public: * @param uncompressedPixelData uncompressed pixel data stored in this element * @param pixelStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ static OFCondition decode( @@ -352,7 +371,8 @@ public: const DcmRepresentationParameter * fromParam, DcmPixelSequence * fromPixSeq, DcmPolymorphOBOW& uncompressedPixelData, - DcmStack & pixelStack); + DcmStack & pixelStack, + OFBool& removeOldRep); /** looks for a codec that is able to decode from the given transfer syntax * and calls the decodeFrame() method of the codec. A read lock on the list of @@ -405,6 +425,10 @@ public: * allocated on heap) returned in this parameter upon success. * @param pixelStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ static OFCondition encode( @@ -414,7 +438,8 @@ public: const E_TransferSyntax toRepType, const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, - DcmStack & pixelStack); + DcmStack & pixelStack, + OFBool& removeOldRep); /** looks for a codec that is able to transcode (re-compresses) * from the given transfer syntax to the given transfer syntax @@ -431,6 +456,10 @@ public: * allocated on heap) returned in this parameter upon success. * @param pixelStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ static OFCondition encode( @@ -440,7 +469,8 @@ public: const E_TransferSyntax toRepType, const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, - DcmStack & pixelStack); + DcmStack & pixelStack, + OFBool& removeOldRep); /** looks for a codec that claims to be able to convert * between the given transfer syntaxes. diff --git a/dcmdata/include/dcmtk/dcmdata/dcdatset.h b/dcmdata/include/dcmtk/dcmdata/dcdatset.h index 63ea8be9..f46ff71f 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcdatset.h +++ b/dcmdata/include/dcmtk/dcmdata/dcdatset.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -281,20 +281,6 @@ class DCMTK_DCMDATA_EXPORT DcmDataset virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); - /** write object in JSON format. - * @tparam Format the formatter class, e.g. DcmJsonFormatPretty. - * Will be deduced automatically. - * @param out output stream to which the JSON document is written - * @param format used to format and customize the output - * @return status, EC_Normal if successful, an error code otherwise - */ - template - OFCondition writeJson(STD_NAMESPACE ostream &out, - Format format) - { - return writeJson(out, OFstatic_cast(DcmJsonFormat&, format)); - } - /** load object from a DICOM file. * This method only supports DICOM objects stored as a dataset, i.e. without meta header. * Use DcmFileFormat::loadFile() to load files with meta header. diff --git a/dcmdata/include/dcmtk/dcmdata/dcdeftag.h b/dcmdata/include/dcmtk/dcmdata/dcdeftag.h index 11751552..a65b51ce 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcdeftag.h +++ b/dcmdata/include/dcmtk/dcmdata/dcdeftag.h @@ -4,7 +4,7 @@ ** ** User: joergr ** Host: thinkpad -** Date: 2019-08-07 18:58:15 +** Date: 2020-11-24 14:49:52 ** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdeftag ** ** From: ../data/dicom.dic @@ -17,12 +17,12 @@ #include "dcmtk/dcmdata/dctagkey.h" -#define DCM_DICT_DEFTAG_BUILD_DATE "2019-08-07 18:58:15" +#define DCM_DICT_DEFTAG_BUILD_DATE "2020-11-24 14:49:52" /* ** Fixed Tags in ascending (gggg,eeee) order. -** Number of entries: 4722 +** Number of entries: 4829 ** Tags with a repeating component (repeating tags) are listed later. */ #define DCM_CommandGroupLength DcmTagKey(0x0000, 0x0000) @@ -81,6 +81,16 @@ #define DCM_SourceApplicationEntityTitle DcmTagKey(0x0002, 0x0016) #define DCM_SendingApplicationEntityTitle DcmTagKey(0x0002, 0x0017) #define DCM_ReceivingApplicationEntityTitle DcmTagKey(0x0002, 0x0018) +#define DCM_SourcePresentationAddress DcmTagKey(0x0002, 0x0026) +#define DCM_SendingPresentationAddress DcmTagKey(0x0002, 0x0027) +#define DCM_ReceivingPresentationAddress DcmTagKey(0x0002, 0x0028) +#define DCM_RTVMetaInformationVersion DcmTagKey(0x0002, 0x0031) +#define DCM_RTVCommunicationSOPClassUID DcmTagKey(0x0002, 0x0032) +#define DCM_RTVCommunicationSOPInstanceUID DcmTagKey(0x0002, 0x0033) +#define DCM_RTVSourceIdentifier DcmTagKey(0x0002, 0x0035) +#define DCM_RTVFlowIdentifier DcmTagKey(0x0002, 0x0036) +#define DCM_RTVFlowRTPSamplingRate DcmTagKey(0x0002, 0x0037) +#define DCM_RTVFlowActualFrameDuration DcmTagKey(0x0002, 0x0038) #define DCM_PrivateInformationCreatorUID DcmTagKey(0x0002, 0x0100) #define DCM_PrivateInformation DcmTagKey(0x0002, 0x0102) #define DCM_FileSetID DcmTagKey(0x0004, 0x1130) @@ -102,6 +112,7 @@ #define DCM_ReferencedTransferSyntaxUIDInFile DcmTagKey(0x0004, 0x1512) #define DCM_ReferencedRelatedGeneralSOPClassUIDInFile DcmTagKey(0x0004, 0x151a) #define DCM_RETIRED_NumberOfReferences DcmTagKey(0x0004, 0x1600) +#define DCM_CurrentFrameFunctionalGroupsSequence DcmTagKey(0x0006, 0x0001) #define DCM_RETIRED_LengthToEnd DcmTagKey(0x0008, 0x0001) #define DCM_SpecificCharacterSet DcmTagKey(0x0008, 0x0005) #define DCM_LanguageCodeSequence DcmTagKey(0x0008, 0x0006) @@ -296,6 +307,7 @@ #define DCM_RETIRED_AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial DcmTagKey(0x0008, 0x225a) #define DCM_RETIRED_OnAxisBackgroundAnatomicStructureCodeSequenceTrial DcmTagKey(0x0008, 0x225c) #define DCM_AlternateRepresentationSequence DcmTagKey(0x0008, 0x3001) +#define DCM_AvailableTransferSyntaxUID DcmTagKey(0x0008, 0x3002) #define DCM_IrradiationEventUID DcmTagKey(0x0008, 0x3010) #define DCM_SourceIrradiationEventSequence DcmTagKey(0x0008, 0x3011) #define DCM_RadiopharmaceuticalAdministrationEventUID DcmTagKey(0x0008, 0x3012) @@ -714,6 +726,11 @@ #define DCM_GPSAreaInformation DcmTagKey(0x0016, 0x008c) #define DCM_GPSDateStamp DcmTagKey(0x0016, 0x008d) #define DCM_GPSDifferential DcmTagKey(0x0016, 0x008e) +#define DCM_LightSourcePolarization DcmTagKey(0x0016, 0x1001) +#define DCM_EmitterColorTemperature DcmTagKey(0x0016, 0x1002) +#define DCM_ContactMethod DcmTagKey(0x0016, 0x1003) +#define DCM_ImmersionMedia DcmTagKey(0x0016, 0x1004) +#define DCM_OpticalMagnificationFactor DcmTagKey(0x0016, 0x1005) #define DCM_ContrastBolusAgent DcmTagKey(0x0018, 0x0010) #define DCM_ContrastBolusAgentSequence DcmTagKey(0x0018, 0x0012) #define DCM_ContrastBolusT1Relaxivity DcmTagKey(0x0018, 0x0013) @@ -989,6 +1006,7 @@ #define DCM_RETIRED_AcquisitionComments DcmTagKey(0x0018, 0x4000) #define DCM_OutputPower DcmTagKey(0x0018, 0x5000) #define DCM_TransducerData DcmTagKey(0x0018, 0x5010) +#define DCM_TransducerIdentificationSequence DcmTagKey(0x0018, 0x5011) #define DCM_FocusDepth DcmTagKey(0x0018, 0x5012) #define DCM_ProcessingFunction DcmTagKey(0x0018, 0x5020) #define DCM_RETIRED_PostprocessingFunction DcmTagKey(0x0018, 0x5021) @@ -2236,6 +2254,18 @@ #define DCM_ReasonForVisitCodeSequence DcmTagKey(0x0032, 0x1067) #define DCM_RequestedContrastAgent DcmTagKey(0x0032, 0x1070) #define DCM_RETIRED_StudyComments DcmTagKey(0x0032, 0x4000) +#define DCM_FlowIdentifierSequence DcmTagKey(0x0034, 0x0001) +#define DCM_FlowIdentifier DcmTagKey(0x0034, 0x0002) +#define DCM_FlowTransferSyntaxUID DcmTagKey(0x0034, 0x0003) +#define DCM_FlowRTPSamplingRate DcmTagKey(0x0034, 0x0004) +#define DCM_SourceIdentifier DcmTagKey(0x0034, 0x0005) +#define DCM_FrameOriginTimestamp DcmTagKey(0x0034, 0x0007) +#define DCM_IncludesImagingSubject DcmTagKey(0x0034, 0x0008) +#define DCM_FrameUsefulnessGroupSequence DcmTagKey(0x0034, 0x0009) +#define DCM_RealTimeBulkDataFlowSequence DcmTagKey(0x0034, 0x000a) +#define DCM_CameraPositionGroupSequence DcmTagKey(0x0034, 0x000b) +#define DCM_IncludesInformation DcmTagKey(0x0034, 0x000c) +#define DCM_TimeOfFrameGroupSequence DcmTagKey(0x0034, 0x000d) #define DCM_ReferencedPatientAliasSequence DcmTagKey(0x0038, 0x0004) #define DCM_VisitStatusID DcmTagKey(0x0038, 0x0008) #define DCM_AdmissionID DcmTagKey(0x0038, 0x0010) @@ -2304,6 +2334,13 @@ #define DCM_MultiplexedAudioChannelsDescriptionCodeSequence DcmTagKey(0x003a, 0x0300) #define DCM_ChannelIdentificationCode DcmTagKey(0x003a, 0x0301) #define DCM_ChannelMode DcmTagKey(0x003a, 0x0302) +#define DCM_MultiplexGroupUID DcmTagKey(0x003a, 0x0310) +#define DCM_PowerlineFrequency DcmTagKey(0x003a, 0x0311) +#define DCM_ChannelImpedanceSequence DcmTagKey(0x003a, 0x0312) +#define DCM_ImpedanceValue DcmTagKey(0x003a, 0x0313) +#define DCM_ImpedanceMeasurementDateTime DcmTagKey(0x003a, 0x0314) +#define DCM_ImpedanceMeasurementFrequency DcmTagKey(0x003a, 0x0315) +#define DCM_ImpedanceMeasurementCurrentType DcmTagKey(0x003a, 0x0316) #define DCM_ScheduledStationAETitle DcmTagKey(0x0040, 0x0001) #define DCM_ScheduledProcedureStepStartDate DcmTagKey(0x0040, 0x0002) #define DCM_ScheduledProcedureStepStartTime DcmTagKey(0x0040, 0x0003) @@ -2600,6 +2637,14 @@ #define DCM_RETIRED_RelationshipSequenceTrial DcmTagKey(0x0040, 0xa731) #define DCM_RETIRED_RelationshipTypeCodeSequenceTrial DcmTagKey(0x0040, 0xa732) #define DCM_RETIRED_LanguageCodeSequenceTrial DcmTagKey(0x0040, 0xa744) +#define DCM_TabulatedValuesSequence DcmTagKey(0x0040, 0xa801) +#define DCM_NumberOfTableRows DcmTagKey(0x0040, 0xa802) +#define DCM_NumbeOfTableColumns DcmTagKey(0x0040, 0xa803) +#define DCM_TableRowNumber DcmTagKey(0x0040, 0xa804) +#define DCM_TableColumnNumber DcmTagKey(0x0040, 0xa805) +#define DCM_TableRowDefinitionSequence DcmTagKey(0x0040, 0xa806) +#define DCM_TableColumnDefinitionSequence DcmTagKey(0x0040, 0xa807) +#define DCM_CellValuesSequence DcmTagKey(0x0040, 0xa808) #define DCM_RETIRED_UniformResourceLocatorTrial DcmTagKey(0x0040, 0xa992) #define DCM_WaveformAnnotationSequence DcmTagKey(0x0040, 0xb020) #define DCM_TemplateIdentifier DcmTagKey(0x0040, 0xdb00) @@ -3076,6 +3121,8 @@ #define DCM_ModelModification DcmTagKey(0x0068, 0x7001) #define DCM_ModelMirroring DcmTagKey(0x0068, 0x7002) #define DCM_ModelUsageCodeSequence DcmTagKey(0x0068, 0x7003) +#define DCM_ModelGroupUID DcmTagKey(0x0068, 0x7004) +#define DCM_RelativeURIReferenceWithinEncapsulatedDocument DcmTagKey(0x0068, 0x7005) #define DCM_GraphicAnnotationSequence DcmTagKey(0x0070, 0x0001) #define DCM_GraphicLayer DcmTagKey(0x0070, 0x0002) #define DCM_BoundingBoxAnnotationUnits DcmTagKey(0x0070, 0x0003) @@ -3321,6 +3368,9 @@ #define DCM_SelectorSSValue DcmTagKey(0x0072, 0x007e) #define DCM_SelectorUIValue DcmTagKey(0x0072, 0x007f) #define DCM_SelectorCodeSequenceValue DcmTagKey(0x0072, 0x0080) +#define DCM_SelectorOVValue DcmTagKey(0x0072, 0x0081) +#define DCM_SelectorSVValue DcmTagKey(0x0072, 0x0082) +#define DCM_SelectorUVValue DcmTagKey(0x0072, 0x0083) #define DCM_NumberOfScreens DcmTagKey(0x0072, 0x0100) #define DCM_NominalScreenDefinitionSequence DcmTagKey(0x0072, 0x0102) #define DCM_NumberOfVerticalPixels DcmTagKey(0x0072, 0x0104) @@ -3951,7 +4001,7 @@ #define DCM_RepeatFractionCycleLength DcmTagKey(0x300a, 0x007a) #define DCM_FractionPattern DcmTagKey(0x300a, 0x007b) #define DCM_NumberOfBeams DcmTagKey(0x300a, 0x0080) -#define DCM_BeamDoseSpecificationPoint DcmTagKey(0x300a, 0x0082) +#define DCM_RETIRED_BeamDoseSpecificationPoint DcmTagKey(0x300a, 0x0082) #define DCM_ReferencedDoseReferenceUID DcmTagKey(0x300a, 0x0083) #define DCM_BeamDose DcmTagKey(0x300a, 0x0084) #define DCM_BeamMeterset DcmTagKey(0x300a, 0x0086) @@ -4253,6 +4303,7 @@ #define DCM_ScanSpotReorderingAllowed DcmTagKey(0x300a, 0x0395) #define DCM_ScanSpotMetersetWeights DcmTagKey(0x300a, 0x0396) #define DCM_ScanningSpotSize DcmTagKey(0x300a, 0x0398) +#define DCM_ScanSpotSizesDelivered DcmTagKey(0x300a, 0x0399) #define DCM_NumberOfPaintings DcmTagKey(0x300a, 0x039a) #define DCM_IonToleranceTableSequence DcmTagKey(0x300a, 0x03a0) #define DCM_IonBeamSequence DcmTagKey(0x300a, 0x03a2) @@ -4271,6 +4322,7 @@ #define DCM_GeneralAccessoryType DcmTagKey(0x300a, 0x0423) #define DCM_GeneralAccessoryNumber DcmTagKey(0x300a, 0x0424) #define DCM_SourceToGeneralAccessoryDistance DcmTagKey(0x300a, 0x0425) +#define DCM_IsocenterToGeneralAccessoryDistance DcmTagKey(0x300a, 0x0426) #define DCM_ApplicatorGeometrySequence DcmTagKey(0x300a, 0x0431) #define DCM_ApplicatorApertureShape DcmTagKey(0x300a, 0x0432) #define DCM_ApplicatorOpening DcmTagKey(0x300a, 0x0433) @@ -4365,7 +4417,7 @@ #define DCM_RTBeamLimitingDeviceProximalDistance DcmTagKey(0x300a, 0x0642) #define DCM_RTBeamLimitingDeviceDistalDistance DcmTagKey(0x300a, 0x0643) #define DCM_ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence DcmTagKey(0x300a, 0x0644) -#define DCM_BeamsModifierOrientationAngle DcmTagKey(0x300a, 0x0645) +#define DCM_BeamModifierOrientationAngle DcmTagKey(0x300a, 0x0645) #define DCM_FixedRTBeamDelimiterDeviceSequence DcmTagKey(0x300a, 0x0646) #define DCM_ParallelRTBeamDelimiterDeviceSequence DcmTagKey(0x300a, 0x0647) #define DCM_NumberOfParallelRTBeamDelimiters DcmTagKey(0x300a, 0x0648) @@ -4434,6 +4486,48 @@ #define DCM_NumberOfPatientSupportDevices DcmTagKey(0x300a, 0x0687) #define DCM_RTBeamModifierDefinitionDistance DcmTagKey(0x300a, 0x0688) #define DCM_BeamAreaLimitSequence DcmTagKey(0x300a, 0x0689) +#define DCM_ReferencedRTPrescriptionSequence DcmTagKey(0x300a, 0x068a) +#define DCM_TreatmentSessionUID DcmTagKey(0x300a, 0x0700) +#define DCM_RTRadiationUsage DcmTagKey(0x300a, 0x0701) +#define DCM_ReferencedRTRadiationSetSequence DcmTagKey(0x300a, 0x0702) +#define DCM_ReferencedRTRadiationRecordSequence DcmTagKey(0x300a, 0x0703) +#define DCM_RTRadiationSetDeliveryNumber DcmTagKey(0x300a, 0x0704) +#define DCM_ClinicalFractionNumber DcmTagKey(0x300a, 0x0705) +#define DCM_RTTreatmentFractionCompletionStatus DcmTagKey(0x300a, 0x0706) +#define DCM_RTRadiationSetUsage DcmTagKey(0x300a, 0x0707) +#define DCM_TreatmentDeliveryContinuationFlag DcmTagKey(0x300a, 0x0708) +#define DCM_TreatmentRecordContentOrigin DcmTagKey(0x300a, 0x0709) +#define DCM_RTTreatmentTerminationStatus DcmTagKey(0x300a, 0x0714) +#define DCM_RTTreatmentTerminationReasonCodeSequence DcmTagKey(0x300a, 0x0715) +#define DCM_MachineSpecificTreatmentTerminationCodeSequence DcmTagKey(0x300a, 0x0716) +#define DCM_RTRadiationSalvageRecordControlPointSequence DcmTagKey(0x300a, 0x0722) +#define DCM_StartingMetersetValueKnownFlag DcmTagKey(0x300a, 0x0723) +#define DCM_TreatmentTerminationDescription DcmTagKey(0x300a, 0x0730) +#define DCM_TreatmentToleranceViolationSequence DcmTagKey(0x300a, 0x0731) +#define DCM_TreatmentToleranceViolationCategory DcmTagKey(0x300a, 0x0732) +#define DCM_TreatmentToleranceViolationAttributeSequence DcmTagKey(0x300a, 0x0733) +#define DCM_TreatmentToleranceViolationDescription DcmTagKey(0x300a, 0x0734) +#define DCM_TreatmentToleranceViolationIdentification DcmTagKey(0x300a, 0x0735) +#define DCM_TreatmentToleranceViolationDateTime DcmTagKey(0x300a, 0x0736) +#define DCM_RecordedRTControlPointDateTime DcmTagKey(0x300a, 0x073a) +#define DCM_ReferencedRadiationRTControlPointIndex DcmTagKey(0x300a, 0x073b) +#define DCM_AlternateValueSequence DcmTagKey(0x300a, 0x073e) +#define DCM_ConfirmationSequence DcmTagKey(0x300a, 0x073f) +#define DCM_InterlockSequence DcmTagKey(0x300a, 0x0740) +#define DCM_InterlockDateTime DcmTagKey(0x300a, 0x0741) +#define DCM_InterlockDescription DcmTagKey(0x300a, 0x0742) +#define DCM_InterlockOriginatingDeviceSequence DcmTagKey(0x300a, 0x0743) +#define DCM_InterlockCodeSequence DcmTagKey(0x300a, 0x0744) +#define DCM_InterlockResolutionCodeSequence DcmTagKey(0x300a, 0x0745) +#define DCM_InterlockResolutionUserSequence DcmTagKey(0x300a, 0x0746) +#define DCM_OverrideDateTime DcmTagKey(0x300a, 0x0760) +#define DCM_TreatmentToleranceViolationTypeCodeSequence DcmTagKey(0x300a, 0x0761) +#define DCM_TreatmentToleranceViolationCauseCodeSequence DcmTagKey(0x300a, 0x0762) +#define DCM_MeasuredMetersetToDoseMappingSequence DcmTagKey(0x300a, 0x0772) +#define DCM_ReferencedExpectedInVivoMeasurementValueIndex DcmTagKey(0x300a, 0x0773) +#define DCM_DoseMeasurementDeviceCodeSequence DcmTagKey(0x300a, 0x0774) +#define DCM_AdditionalParameterRecordingInstanceSequence DcmTagKey(0x300a, 0x0780) +#define DCM_InterlockOriginDescription DcmTagKey(0x300a, 0x0783) #define DCM_ReferencedRTPlanSequence DcmTagKey(0x300c, 0x0002) #define DCM_ReferencedBeamSequence DcmTagKey(0x300c, 0x0004) #define DCM_ReferencedBeamNumber DcmTagKey(0x300c, 0x0006) @@ -4518,6 +4612,7 @@ #define DCM_SegmentAnnotationTypeCodeSequence DcmTagKey(0x3010, 0x002c) #define DCM_DeviceLabel DcmTagKey(0x3010, 0x002d) #define DCM_DeviceTypeCodeSequence DcmTagKey(0x3010, 0x002e) +#define DCM_SegmentAnnotationTypeModifierCodeSequence DcmTagKey(0x3010, 0x002f) #define DCM_PatientEquipmentRelationshipCodeSequence DcmTagKey(0x3010, 0x0030) #define DCM_ReferencedFiducialsUID DcmTagKey(0x3010, 0x0031) #define DCM_PatientTreatmentOrientationSequence DcmTagKey(0x3010, 0x0032) @@ -4606,6 +4701,18 @@ #define DCM_IntendedStartDayOfWeek DcmTagKey(0x3010, 0x0086) #define DCM_WeekdayFractionPatternSequence DcmTagKey(0x3010, 0x0087) #define DCM_DeliveryTimeStructureCodeSequence DcmTagKey(0x3010, 0x0088) +#define DCM_TreatmentSiteModifierCodeSequence DcmTagKey(0x3010, 0x0089) +#define DCM_RoboticBaseLocationIndicator DcmTagKey(0x3010, 0x0090) +#define DCM_RoboticPathNodeSetCodeSequence DcmTagKey(0x3010, 0x0091) +#define DCM_RoboticNodeIdentifier DcmTagKey(0x3010, 0x0092) +#define DCM_RTTreatmentSourceCoordinates DcmTagKey(0x3010, 0x0093) +#define DCM_RadiationSourceCoordinateSystemYawAngle DcmTagKey(0x3010, 0x0094) +#define DCM_RadiationSourceCoordinateSystemRollAngle DcmTagKey(0x3010, 0x0095) +#define DCM_RadiationSourceCoordinateSystemPitchAngle DcmTagKey(0x3010, 0x0096) +#define DCM_RoboticPathControlPointSequence DcmTagKey(0x3010, 0x0097) +#define DCM_TomotherapeuticControlPointSequence DcmTagKey(0x3010, 0x0098) +#define DCM_TomotherapeuticLeafOpenDurations DcmTagKey(0x3010, 0x0099) +#define DCM_TomotherapeuticLeafInitialClosedDurations DcmTagKey(0x3010, 0x009a) #define DCM_RETIRED_Arbitrary DcmTagKey(0x4000, 0x0010) #define DCM_RETIRED_TextComments DcmTagKey(0x4000, 0x4000) #define DCM_RETIRED_ResultsID DcmTagKey(0x4008, 0x0040) @@ -4671,7 +4778,7 @@ #define DCM_RouteSegmentEndTime DcmTagKey(0x4010, 0x1026) #define DCM_TDRType DcmTagKey(0x4010, 0x1027) #define DCM_InternationalRouteSegment DcmTagKey(0x4010, 0x1028) -#define DCM_ThreatDetectionAlgorithmandVersion DcmTagKey(0x4010, 0x1029) +#define DCM_ThreatDetectionAlgorithmAndVersion DcmTagKey(0x4010, 0x1029) #define DCM_AssignedLocation DcmTagKey(0x4010, 0x102a) #define DCM_AlarmDecisionTime DcmTagKey(0x4010, 0x102b) #define DCM_AlarmDecision DcmTagKey(0x4010, 0x1031) diff --git a/dcmdata/include/dcmtk/dcmdata/dcelem.h b/dcmdata/include/dcmtk/dcmdata/dcelem.h index 87b8a5a2..1aeff051 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcelem.h +++ b/dcmdata/include/dcmtk/dcmdata/dcelem.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -721,7 +721,7 @@ class DCMTK_DCMDATA_EXPORT DcmElement * which must be large enough to contain a complete frame. * @param dataset pointer to DICOM dataset in which this pixel data object is * located. Used to access rows, columns, samples per pixel etc. - * @param frameNo numer of frame, starting with 0 for the first frame. + * @param frameNo number of frame, starting with 0 for the first frame. * @param startFragment index of the compressed fragment that contains * all or the first part of the compressed bitstream for the given frameNo. * Upon successful return this parameter is updated to contain the index @@ -882,7 +882,7 @@ class DCMTK_DCMDATA_EXPORT DcmElement protected: /** This function returns this element's value. The returned value corresponds to the - * byte ordering (little or big endian) that was passed. + * byte ordering (little or big endian) that was passed. * @param newByteOrder The byte ordering that shall be accounted * for (little or big endian). */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcerror.h b/dcmdata/include/dcmtk/dcmdata/dcerror.h index cb71d1a0..ab13bad6 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcerror.h +++ b/dcmdata/include/dcmtk/dcmdata/dcerror.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -72,6 +72,7 @@ const unsigned short OFM_dcmfg = 31; const unsigned short OFM_dcmtract = 32; const unsigned short OFM_dcmpmap = 33; const unsigned short OFM_dcmelekt = 34; +const unsigned short OFM_dcmect = 35; // condition constants @@ -170,6 +171,11 @@ extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_VOI_LUT_OBOW; extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_PixelDataExplLengthIllegal; /// Element length is larger than 32-bit length field permits extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ElemLengthExceeds32BitField; +/// Cannot write 'nan' or 'inf' as JSON number +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteJsonNumber; +/// Cannot write compressed pixel data JSON InlineBinary +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteJsonInlineBinary; + //@} // status code constants diff --git a/dcmdata/include/dcmtk/dcmdata/dcfilefo.h b/dcmdata/include/dcmtk/dcmdata/dcfilefo.h index c8338364..a95a4628 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcfilefo.h +++ b/dcmdata/include/dcmtk/dcmdata/dcfilefo.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -128,11 +128,13 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat /** make sure that all data elements of the file meta information header are existent * in metainfo and contain correct values. * @param oxfer the transfer syntax which shall be used - * @param writeMode flag indicating whether to update the file meta information or not + * @param writeMode flag indicating whether to update the file meta information or not. + * The default behavior is to delete all old meta information in order to create + * it from scratch. * @return EC_Normal if valid, an error code otherwise */ virtual OFCondition validateMetaInfo(const E_TransferSyntax oxfer, - const E_FileWriteMode writeMode = EWM_fileformat); + const E_FileWriteMode writeMode = EWM_createNewMeta); /** get file meta information header part of the fileformat * @return reference to internally stored file meta information header @@ -221,6 +223,8 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat * DcmFileFormat to the DcmDataset object. * @param writeMode write file with or without meta header. Also allows for * updating the information in the file meta information header. + * The default behavior is to delete all old meta information in order to + * create it from scratch. * @return status, EC_Normal if successful, an error code otherwise */ virtual OFCondition write(DcmOutputStream &outStream, @@ -232,7 +236,7 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat const Uint32 padlen = 0, const Uint32 subPadlen = 0, Uint32 instanceLength = 0, - const E_FileWriteMode writeMode = EWM_fileformat); + const E_FileWriteMode writeMode = EWM_createNewMeta); /** write object in XML format. * The XML declaration (e.g. ) is not written by this function. @@ -251,20 +255,6 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); - /** write object in JSON format. - * @tparam Format the formatter class, e.g. DcmJsonFormatPretty. - * Will be deduced automatically. - * @param out output stream to which the JSON document is written - * @param format used to format and customize the output - * @return status, EC_Normal if successful, an error code otherwise - */ - template - OFCondition writeJson(STD_NAMESPACE ostream &out, - Format format) - { - return writeJson(out, OFstatic_cast(DcmJsonFormat&, format)); - } - /** load object from a DICOM file. * This method supports DICOM objects stored as a file (with meta header) or as a * dataset (without meta header). By default, the presence of a meta header is @@ -323,7 +313,9 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat * @param padLength number of bytes used for the dataset padding (has to be an even number) * @param subPadLength number of bytes used for the item padding (has to be an even number) * @param writeMode write file with or without meta header. Also allows for updating the - * information in the file meta information header. + * information in the file meta information header. The default behavior is to delete + * all old meta information in order to create it from scratch. + * * @return status, EC_Normal if successful, an error code otherwise */ virtual OFCondition saveFile(const OFFilename &fileName, @@ -333,7 +325,7 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat const E_PaddingEncoding padEncoding = EPD_noChange, const Uint32 padLength = 0, const Uint32 subPadLength = 0, - const E_FileWriteMode writeMode = EWM_fileformat); + const E_FileWriteMode writeMode = EWM_createNewMeta); // methods for different pixel representations diff --git a/dcmdata/include/dcmtk/dcmdata/dcitem.h b/dcmdata/include/dcmtk/dcmdata/dcitem.h index 5a4afc4f..eaa222c2 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcitem.h +++ b/dcmdata/include/dcmtk/dcmdata/dcitem.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -175,21 +175,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const char *pixelFileName = NULL, size_t *pixelCounter = NULL); - /** calculate the length of this DICOM element when encoded with the - * given transfer syntax and the given encoding type for sequences. - * For elements, the length includes the length of the tag, length field, - * VR field and the value itself, for items and sequences it returns - * the length of the complete item or sequence including delimitation tags - * if applicable. - * If length encoding is set to be explicit and the total item size is - * larger than the available 32-bit length field, then undefined length - * is returned. If "dcmWriteOversizedSeqsAndItemsImplicit" is disabled, - * also the internal DcmObject errorFlag is set to EC_SeqOrItemContentOverflow - * in case the item content (excluding tag header etc.) is already too - * large. - * @param xfer transfer syntax for length calculation - * @param enctype sequence encoding type for length calculation - * @return length of DICOM element + /** @copydoc DcmObject::calcElementLength() */ virtual Uint32 calcElementLength(const E_TransferSyntax xfer, const E_EncodingType enctype); @@ -301,6 +287,19 @@ class DCMTK_DCMDATA_EXPORT DcmItem virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); + /** write object in JSON format and control whether the output + * is encapsulated in braces + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @param printBraces true if output should be encapsulated in braces + * @param printNewline true if a newline should be printed after a closing brace + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJsonExt(STD_NAMESPACE ostream &out, + DcmJsonFormat &format, + OFBool printBraces, + OFBool printNewline); + /** special write method for creation of digital signatures * @param outStream DICOM output stream * @param oxfer output transfer syntax @@ -560,7 +559,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem * will be handled. * @param padlen The length up to which the dataset shall be padded, * if padding is desired. - * @param subPadlen For sequences (ie sub elements), the length up to + * @param subPadlen For sequences (i.e. sub elements), the length up to * which item shall be padded, if padding is desired. * @param instanceLength Number of extra bytes added to the item/dataset * length used when computing the padding; this @@ -625,7 +624,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** find element and get value as a reference to a C string. NB: The string is not copied! * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, - * UR, UT + * UR, UT. * Since the getString() routine is called internally the resulting string reference represents * the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed. * The result variable 'value' is automatically set to NULL if an error occurs. @@ -640,7 +639,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** find element and get value as a reference to a C string. NB: The string is not copied! * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, - * UR, UT + * UR, UT. * Since the getString() routine is called internally the resulting string reference represents * the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed. * The result variable 'value' is automatically set to NULL and 'length' is set to 0 if an error @@ -660,7 +659,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** find element and get value as a C++ string (only one component). * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, - * OL, OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * Since the getOFString() routine is called internally the resulting string is normalized, i.e. * leading and/or trailing spaces are removed according to the associated value representation, * or the element value is converted to a character string (for non-string VRs) - see documentation @@ -681,7 +680,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** find element and get value as a C++ string (all components). * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, - * OL, OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * Since the getOFStringArray() routine is called internally the resulting string is normalized, * i.e. leading and/or trailing spaces are removed according to the associated value representation * or the element values are converted to character strings (for non-string VRs) - see documentation @@ -697,7 +696,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an unsigned 8-bit integer. - * Applicable to the following VRs: OB + * Applicable to the following VRs: OB. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -711,7 +710,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of unsigned 8-bit integers. - * Applicable to the following VRs: OB + * Applicable to the following VRs: OB. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -725,7 +724,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an unsigned 16-bit integer. - * Applicable to the following VRs: OW, US + * Applicable to the following VRs: OW, US. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -739,7 +738,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of unsigned 16-bit integers. - * Applicable to the following VRs: AT, OW, US + * Applicable to the following VRs: AT, OW, US. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -753,7 +752,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a signed 16-bit integer. - * Applicable to the following VRs: SS + * Applicable to the following VRs: SS. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -767,7 +766,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of signed 16-bit integers. - * Applicable to the following VRs: SS + * Applicable to the following VRs: SS. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -781,7 +780,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an unsigned 32-bit integer. - * Applicable to the following VRs: OL, UL + * Applicable to the following VRs: OL, UL. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -795,7 +794,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of unsigned 32-bit integers. - * Applicable to the following VRs: OL, UL + * Applicable to the following VRs: OL, UL. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -809,7 +808,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a signed 32-bit integer. - * Applicable to the following VRs: IS, SL + * Applicable to the following VRs: IS, SL. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -823,7 +822,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of signed 32-bit integers. - * Applicable to the following VRs: SL + * Applicable to the following VRs: SL. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -837,7 +836,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an unsigned 64-bit integer. - * Applicable to the following VRs: OV, UV + * Applicable to the following VRs: OV, UV. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -851,7 +850,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of unsigned 64-bit integers. - * Applicable to the following VRs: OV, UV + * Applicable to the following VRs: OV, UV. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -865,7 +864,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a signed 64-bit integer. - * Applicable to the following VRs: SV + * Applicable to the following VRs: SV. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -879,7 +878,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of signed 64-bit integers. - * Applicable to the following VRs: SV + * Applicable to the following VRs: SV. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -893,7 +892,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a (signed) long integer. - * Applicable to the following VRs: IS, OL, SL, SS, UL, US + * Applicable to the following VRs: IS, OL, SL, SS, UL, US. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -907,7 +906,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a 32-bit floating point. - * Applicable to the following VRs: FL, OF + * Applicable to the following VRs: FL, OF. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -921,7 +920,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of 32-bit floating point values. - * Applicable to the following VRs: FL, OF + * Applicable to the following VRs: FL, OF. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -935,7 +934,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as a 64-bit floating point. - * Applicable to the following VRs: DS, FD, OD + * Applicable to the following VRs: DS, FD, OD. * The result variable 'value' is automatically set to zero if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the element value is stored @@ -949,7 +948,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** find element and get value as an array of 64-bit floating point values. - * Applicable to the following VRs: FD, OD + * Applicable to the following VRs: FD, OD. * The result variable 'value' is automatically set to NULL if an error occurs. * @param tagKey DICOM tag specifying the attribute to be searched for * @param value variable in which the reference to the element value is stored @@ -963,7 +962,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** looks up and returns a given sequence. - * Applicable to the following VRs: SQ, (pixelSQ) + * Applicable to the following VRs: SQ, (pixelSQ). * The result variable 'sequence' is automatically set to NULL if an error occurs * (e.g. if 'seqTagKey' does not refer to a sequence attribute). * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for @@ -981,7 +980,8 @@ class DCMTK_DCMDATA_EXPORT DcmItem * to NULL and returns EC_TagNotFound (specified sequence does not exist) or * EC_IllegalParameter (specified item does not exist). Only the top-most level of * the dataset/item is examined (i.e. no deep-search is performed). - * Applicable to the following VRs: SQ, (pixelSQ) + * Applicable to the following VRs: SQ, (pixelSQ). + * Please note that an instance of the DcmPixelItem class cannot be retrieved. * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for * @param item variable in which the reference to (or copy of) the item is stored * @param itemNum number of the item to be searched for (0..n-1, -1 for last) @@ -1000,7 +1000,9 @@ class DCMTK_DCMDATA_EXPORT DcmItem * If either the sequence or the item do not exist, they are created. If necessary, * multiple empty items are inserted. Only the top-most level of the dataset/item * is examined (i.e. no deep-search is performed). - * Applicable to the following VRs: SQ, (pixelSQ) + * Applicable to the following VRs: SQ, (pixelSQ). + * Please note that an instance of the DcmPixelItem class cannot be retrieved or + * created. * @param seqTag DICOM tag specifying the sequence attribute to be searched for * (or to be created) * @param item variable in which the reference to the sequence item is stored @@ -1042,7 +1044,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool searchIntoSub = OFFalse); /** looks up the given sequence in the current dataset and deletes the given item. - * Applicable to the following VRs: SQ, (pixelSQ) + * Applicable to the following VRs: SQ, (pixelSQ). * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for * @param itemNum number of the item to be deleted (0..n-1, -1 for last) * @return EC_Normal upon success, an error otherwise. @@ -1055,7 +1057,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** create a new element, put specified value to it and insert the element into the dataset/item. * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, - * OL, OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * @param tag DICOM tag specifying the attribute to be created * @param value string value to be set for the new element (might be empty or NULL) * @param replaceOld flag indicating whether to replace an existing element or not @@ -1067,7 +1069,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** create a new element, put specified value to it and insert the element into the dataset/item. * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, - * OL, OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * Please note that since the length of the string has to be specified explicitly, the string * can contain more than one NULL byte. * @param tag DICOM tag specifying the attribute to be created @@ -1082,8 +1084,8 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, - * UR, UT + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element (might be empty) * @param replaceOld flag indicating whether to replace an existing element or not @@ -1094,7 +1096,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: OB, ox (polymorph OB/OW or pixel data) + * Applicable to the following VRs: OB, ox (polymorph OB/OW or pixel data). * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element (might be NULL) * @param count number of values (= bytes in this case) to be copied from 'value' @@ -1107,7 +1109,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: US, xs (US or SS) + * Applicable to the following VRs: US, xs (US or SS). * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1121,7 +1123,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: AT, OW, US, ox (polymorph OB/OW or pixel data), xs (US or SS) + * Applicable to the following VRs: AT, OW, US, ox (polymorph OB/OW or pixel data), xs (US or SS). * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element (might be NULL) * @param count number of values (not bytes!) to be copied from 'value' @@ -1134,7 +1136,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: SS, xs (US or SS) + * Applicable to the following VRs: SS, xs (US or SS). * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1148,7 +1150,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: SS, xs (US or SS) + * Applicable to the following VRs: SS, xs (US or SS). * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param count number of values (not bytes!) to be copied from 'value' @@ -1161,7 +1163,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: OL, UL + * Applicable to the following VRs: OL, UL. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1175,7 +1177,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: OL, UL + * Applicable to the following VRs: OL, UL. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param count number of values (not bytes!) to be copied from 'value' @@ -1188,7 +1190,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: SL + * Applicable to the following VRs: SL. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1202,7 +1204,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: FL, OF + * Applicable to the following VRs: FL, OF. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1216,7 +1218,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: FL, OF + * Applicable to the following VRs: FL, OF. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param count number of values (not bytes!) to be copied from 'value' @@ -1229,7 +1231,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: FD, OD + * Applicable to the following VRs: DS, FD, OD * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1243,7 +1245,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: FD, OD + * Applicable to the following VRs: FD, OD. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param count number of values (not bytes!) to be copied from 'value' @@ -1256,7 +1258,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem const OFBool replaceOld = OFTrue); /** create a new element, put specified value to it and insert the element into the dataset/item. - * Applicable to the following VRs: AT + * Applicable to the following VRs: AT. * @param tag DICOM tag specifying the attribute to be created * @param value value to be set for the new element * @param pos index of the value to be set (0..vm). A value can be appended to @@ -1273,7 +1275,7 @@ class DCMTK_DCMDATA_EXPORT DcmItem /** create a new element (with no value) and insert it into the dataset/item. * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, - * OL, OW, PN, SH, SL, SQ, SS, ST, TM, UC, UI, UL, UR, US, UT + * OL, OV, OW, PN, SH, SL, SQ, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV. * @param tag DICOM tag specifying the attribute to be created * @param replaceOld flag indicating whether to replace an existing element or not * @return EC_Normal upon success, an error code otherwise. @@ -1285,7 +1287,8 @@ class DCMTK_DCMDATA_EXPORT DcmItem * If the sequence does not exist, it is created. If necessary, multiple empty items * are inserted before the specified item position. Only the top-most level of the * dataset/item is examined (i.e. no deep-search is performed). - * Applicable to the following VRs: SQ, (pixelSQ) + * Applicable to the following VRs: SQ, (pixelSQ). + * Please note that an instance of the DcmPixelItem class cannot be inserted. * @param seqTag DICOM tag specifying the sequence attribute to be searched for * (or to be created) * @param item item to be inserted into the sequence, must not be contained in this diff --git a/dcmdata/include/dcmtk/dcmdata/dcjson.h b/dcmdata/include/dcmtk/dcmdata/dcjson.h index d60b18e0..d501dcc8 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcjson.h +++ b/dcmdata/include/dcmtk/dcmdata/dcjson.h @@ -1,6 +1,6 @@ /* * -* Copyright (C) 2017-2018, OFFIS e.V. +* Copyright (C) 2017-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -200,6 +200,7 @@ public: */ inline DcmJsonFormat(const OFBool printMetaInfo) : printMetaheaderInformation(printMetaInfo) + , enableJsonExtension(OFFalse) { } @@ -313,6 +314,21 @@ public: */ virtual void printNextArrayElementPrefix(STD_NAMESPACE ostream &out); + /** return the flag indicating whether extended JSON number encoding is enabled. + */ + virtual OFBool getJsonExtensionEnabled() const + { + return enableJsonExtension; + } + + /** set the flag indicating whether extended JSON number encoding is enabled. + * @param enabled new value of the flag + */ + virtual void setJsonExtensionEnabled(OFBool enabled) + { + enableJsonExtension = enabled; + } + /** Option that defines if metaheader information should be printed. */ const OFBool printMetaheaderInformation; @@ -330,6 +346,16 @@ protected: /** Used for decreasing the indention level. */ virtual void decreaseIndention() = 0; + +private: + + /** Option that defines if the inofficial JSON extension should be + * permitted under which decimal numbers may have the values "-inf", + * "inf" or "nan". Default is OFFalse, in which case such values + * will lead to an error code being returned instead. + */ + OFBool enableJsonExtension; + }; @@ -339,7 +365,7 @@ protected: class DCMTK_DCMDATA_EXPORT DcmJsonFormatPretty : public DcmJsonFormat { private: - /** Variable for the indentenlevel of DcmJsonFormat + /** Variable for the indention level of DcmJsonFormat */ unsigned m_IndentionLevel; diff --git a/dcmdata/include/dcmtk/dcmdata/dcobject.h b/dcmdata/include/dcmtk/dcmdata/dcobject.h index c0d5a683..b62eacfa 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcobject.h +++ b/dcmdata/include/dcmtk/dcmdata/dcobject.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -436,6 +436,18 @@ class DCMTK_DCMDATA_EXPORT DcmObject * actually represent a compound value (e.g. items like DcmPixelItem). * Such overflows will be detected, in which case the maximum possible * value will be returned instead, coinciding with DCM_UndefinedLength. + * @warning The implementation in DcmPixelData may return zero if no + * conforming representation exists and set the + * EC_RepresentationNotFound error flag to indicated it. + * @warning When calculation the length of a sequence or an item + * containing multiple attributes, the implementation may return + * DCM_UndefinedLength to indicate a value that can not be encoded as + * a 32 bit length field. It will even do so if + * "dcmWriteOversizedSeqsAndItemsUndefined" is disabled, but then also + * set the EC_SeqOrItemContentOverflow error flag (inside getLength()) + * to indicated it. + * @note Just check for zero or DCM_UndefinedLength return value and then + * have a look at the error flag in either case. * @param xfer transfer syntax for length calculation * @param enctype sequence encoding type for length calculation * @return length of DICOM element diff --git a/dcmdata/include/dcmtk/dcmdata/dcpath.h b/dcmdata/include/dcmtk/dcmdata/dcpath.h index fe229f38..1d864951 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcpath.h +++ b/dcmdata/include/dcmtk/dcmdata/dcpath.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2008-2017, OFFIS e.V. + * Copyright (C) 2008-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -23,58 +23,67 @@ #ifndef DCPATH_H #define DCPATH_H -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdatset.h" - /** Class representing a node in DcmPath. A node contains just - * a pointer to a DcmObject (e.g. a sequence or an item). Additionally - * an item number is stored which also makes sense in case that the - * object pointed to is an item. The item number is necessary because - * when having only a pointer to a DcmItem there is no way to find out - * at which position the item actually has in the surrounding sequence. - */ + * a pointer to a DcmObject (e.g. a sequence or an item). Additionally + * an item number is stored which also makes sense in case that the + * object pointed to is an item. The item number is necessary because + * when having only a pointer to a DcmItem there is no way to find out + * at which position the item actually has in the surrounding sequence. + */ class DCMTK_DCMDATA_EXPORT DcmPathNode { public: - - /** Constructor. Creates empty path node. - */ - DcmPathNode() : m_obj(NULL), m_itemNo(0) {} - - /** Constructor. Creates search node from object pointer and item number. - * @param obj [in] The object the search node points to. The memory of the - * given DICOM object is not handled by the node itself but - * must be handled (i.e. freed) from outside. - * @param itemNo [in] The item number that should be set. Only relevant - * if obj parameter contains an item - */ - DcmPathNode(DcmObject* obj, Uint32 itemNo) : m_obj(obj), m_itemNo(itemNo) {} - - /** Destructor. Nothing to do, the DICOM object is not freed automatically! - */ - ~DcmPathNode() { } - - /// Pointer to object this search node points to - DcmObject* m_obj; - - /// The item number of the item in m_obj; only useful if m_obj is an item - Uint32 m_itemNo; + /** Constructor. Creates empty path node. + */ + DcmPathNode() + : m_obj(NULL) + , m_itemNo(0) + { + } + + /** Constructor. Creates search node from object pointer and item number. + * @param obj [in] The object the search node points to. The memory of the + * given DICOM object is not handled by the node itself but + * must be handled (i.e. freed) from outside. + * @param itemNo [in] The item number that should be set. Only relevant + * if obj parameter contains an item + */ + DcmPathNode(DcmObject* obj, Uint32 itemNo) + : m_obj(obj) + , m_itemNo(itemNo) + { + } + + /** Destructor. Nothing to do, the DICOM object is not freed automatically! + */ + ~DcmPathNode() + { + } + + /// Pointer to object this search node points to + DcmObject* m_obj; + + /// The item number of the item in m_obj; only useful if m_obj is an item + Uint32 m_itemNo; private: - - /** Private undefined copy constructor - */ - DcmPathNode(const DcmPathNode& rhs); - - /** Private undefined assignment operator - */ - DcmPathNode& operator=(const DcmPathNode& arg); + /** Private undefined copy constructor + * @param rhs Object to copy from + */ + DcmPathNode(const DcmPathNode& rhs); + + /** Private undefined assignment operator + * @param arg Object to copy from + * @return Reference to this object + */ + DcmPathNode& operator=(const DcmPathNode& arg); }; - /** Class representing a path of DICOM objects. A path is a "way" through * a DICOM dataset, i.e. it starts e.g. with an item, followed by a sequence * originally contained in this item. The sequence then could be followed by @@ -86,434 +95,429 @@ class DCMTK_DCMDATA_EXPORT DcmPath { public: - - /** Constructor, creates an empty search result - */ - DcmPath(); - - /** Constructor, creates a search result from a list of search nodes. - * @param currentPath [in] The list of search nodes representing a - * "path" through a DICOM dataset - */ - DcmPath(const OFList& currentPath); - - /** Appends a search node at the end of the search result path. It is not - * checked whether the resulting path is still valid. - * @param node [in] The node to append. - * - */ - void append(DcmPathNode* node); - - /** Removes last path node from path. Also frees memory of path node - * but does _not_ free memory of the underlying DICOM item or element. - * @return none - */ - void deleteBackNode(); - - /** Returns iterator pointing to first path component. - * @return Iterator to first path node. - */ - OFListIterator(DcmPathNode*) begin(); - - /** Returns last path component. - * @return The last path component, NULL if none exists. - */ - DcmPathNode* back(); - - /** Returns iterator pointing to last path component. - * @return Iterator to last path node. - */ - OFListIterator(DcmPathNode*) end(); - - /** Returns number of path components. - * @return The number of path components - */ - Uint32 size() const; - - /** Returns whether path is empty, ie does not contain any path nodes - * @return OFTrue, if path is empty, OFFalse otherwise - */ - OFBool empty() const; - - /** Returns a string representation of the path, - * e.g.\ "SourceImageSequence[0].ReferencedSOPInstanceUID" - * @return String representing path - */ - OFString toString() const; - - /** Returns whether the path contains tags of a given group. - * Might be useful for looking after (unwanted) meta header tags etc. - * @param groupNo [in] The group number to look for - * @return OFTrue if group number is found in path, OFFalse otherwise - */ - OFBool containsGroup(const Uint16 groupNo) const; - - /** Returns a string representation of each path node separately. - * Tags are represented as numbers surrounded by braces "(gggg,eeee)", - * not dictionary names. Items are represented by a number or wildcard - * in square brackets, eg. "[12]" or "[*]". - * @param path The path to parse into different nodes - * @param result [out] List containing the resulting strings - * @return none - */ - static OFCondition separatePathNodes(const OFString& path, OFList& result); - - /** Helper function for findOrCreatePath(). Parses an item number from - * the beginning of the path string. The item number must be positive, - * starting with 0. - * The path must start like "[itemnumber]...". - * @param path [in/out] The path starting with the item number in square - * brackets, e.g.\ "[3]". The parsed item number and a - * potentially following "." are removed from the path - * @param itemNo [out] The parsed item number. If a wildcard was parsed, - * this output parameter is not set at all. - * @param wasWildcard [out] Is set to OFTrue, if wildcard was parsed - * (instead of concrete item number). - * @return EC_Normal, if concrete item number or wildcard was parsed - */ - static OFCondition parseItemNoFromPath(OFString& path, // inout - Uint32& itemNo, // out - OFBool& wasWildcard); // out - - /** Function that parses a tag from the beginning of a path string. - * The tag has to be either in numeric format, e.g. "(0010,0010)" or - * a dictionary name, e.g. "PatientName". If successful, the - * parsed tag is removed from the path string. - * @param path [in/out] The path string, starting with the attribute - * to parse - * @param tag [out] The tag parsed - * @return EC_Normal if successful, error code otherwise - */ - static OFCondition parseTagFromPath(OFString& path, // inout - DcmTag& tag); // out - - /** Desctructor, cleans up memory of path nodes. Does not delete - * the DcmObjects the nodes point to (this is also not done - * by the desctructor of the path nodes, so the caller is responsible - * for freeing any related DICOM objects. - */ - ~DcmPath(); + /** Constructor, creates an empty search result + */ + DcmPath(); + + /** Constructor, creates a search result from a list of search nodes. + * @param currentPath [in] The list of search nodes representing a + * "path" through a DICOM dataset + */ + DcmPath(const OFList& currentPath); + + /** Appends a search node at the end of the search result path. It is not + * checked whether the resulting path is still valid. + * @param node [in] The node to append. + * + */ + void append(DcmPathNode* node); + + /** Removes last path node from path. Also frees memory of path node + * but does _not_ free memory of the underlying DICOM item or element. + * @return none + */ + void deleteBackNode(); + + /** Returns iterator pointing to first path component. + * @return Iterator to first path node. + */ + OFListIterator(DcmPathNode*) begin(); + + /** Returns last path component. + * @return The last path component, NULL if none exists. + */ + DcmPathNode* back(); + + /** Returns iterator pointing to last path component. + * @return Iterator to last path node. + */ + OFListIterator(DcmPathNode*) end(); + + /** Returns number of path components. + * @return The number of path components + */ + Uint32 size() const; + + /** Returns whether path is empty, ie does not contain any path nodes + * @return OFTrue, if path is empty, OFFalse otherwise + */ + OFBool empty() const; + + /** Returns a string representation of the path, + * e.g.\ "SourceImageSequence[0].ReferencedSOPInstanceUID" + * @return String representing path + */ + OFString toString() const; + + /** Returns whether the path contains tags of a given group. + * Might be useful for looking after (unwanted) meta header tags etc. + * @param groupNo [in] The group number to look for + * @return OFTrue if group number is found in path, OFFalse otherwise + */ + OFBool containsGroup(const Uint16 groupNo) const; + + /** Returns a string representation of each path node separately. + * Tags are represented as numbers surrounded by braces "(gggg,eeee)", + * not dictionary names. Items are represented by a number or wildcard + * in square brackets, eg. "[12]" or "[*]". + * @param path The path to parse into different nodes + * @param result [out] List containing the resulting strings + * @return none + */ + static OFCondition separatePathNodes(const OFString& path, OFList& result); + + /** Helper function for findOrCreatePath(). Parses an item number from + * the beginning of the path string. The item number must be positive, + * starting with 0. + * The path must start like "[itemnumber]...". + * @param path [in/out] The path starting with the item number in square + * brackets, e.g.\ "[3]". The parsed item number and a + * potentially following "." are removed from the path + * @param itemNo [out] The parsed item number. If a wildcard was parsed, + * this output parameter is not set at all. + * @param wasWildcard [out] Is set to OFTrue, if wildcard was parsed + * (instead of concrete item number). + * @return EC_Normal, if concrete item number or wildcard was parsed + */ + static OFCondition parseItemNoFromPath(OFString& path, // inout + Uint32& itemNo, // out + OFBool& wasWildcard); // out + + /** Function that parses a tag from the beginning of a path string. + * The tag has to be either in numeric format, e.g. "(0010,0010)" or + * a dictionary name, e.g. "PatientName". If successful, the + * parsed tag is removed from the path string. + * @param path [in/out] The path string, starting with the attribute + * to parse + * @param tag [out] The tag parsed + * @return EC_Normal if successful, error code otherwise + */ + static OFCondition parseTagFromPath(OFString& path, // inout + DcmTag& tag); // out + + /** Desctructor, cleans up memory of path nodes. Does not delete + * the DcmObjects the nodes point to (this is also not done + * by the desctructor of the path nodes, so the caller is responsible + * for freeing any related DICOM objects. + */ + ~DcmPath(); private: - - /// Internal list representing the nodes in the path. - OFList m_path; - - /** Private undefined copy constructor - */ - DcmPath(const DcmPath& rhs); - - /** Private undefined assignment operator - */ - DcmPath& operator=(const DcmPath& arg); + /// Internal list representing the nodes in the path. + OFList m_path; + + /** Private undefined copy constructor + * @param rhs Path to copy from + */ + DcmPath(const DcmPath& rhs); + + /** Private undefined assignment operator + * @param arg Path to copy from + * @return Reference to this object + */ + DcmPath& operator=(const DcmPath& arg); }; - +/// Class that operates on DICOM datasets using a (string) path syntax. class DCMTK_DCMDATA_EXPORT DcmPathProcessor { public: - - /** Constructor, creates an empty search object. - */ - DcmPathProcessor(); - - /** Sets whether searching/creating paths will support wildcard for - * items. If set to false, any path operation with item wildcard characters - * will return an error. - * @param supported [in] If true, wildcard are enabled (default) - * If false, item wildcard support is disabled. - */ - void setItemWildcardSupport(const OFBool supported); - - - /** Enables (class default: enabled) or disables checking of private - * reservations when inserting private tags. If enabled and a private - * tag is created that has no private reservation, an error is returned. - * If disabled, it is possible to insert private tags that do not have - * a reservation in the corresponding item/dataset. - * @param doChecking [in] OFTrue enables reservation checking, - * OFFalse disables it. - */ - void checkPrivateReservations(const OFBool doChecking); - - /** Checks in item, whether a private reservation for a given - * tag key exists. - * @param item [in] The item to search in - * @param tagKey [in/out] The tag to be checked. - * @param privateCreator [in] The private creator to check for (if known, - * can be left empty) - * @return Return EC_Normal if reservation checking was successful. - * Otherwise an error code is returned. - */ - static OFCondition checkPrivateTagReservation(DcmItem* item, - const DcmTagKey& tagKey, - const OFString& privateCreator = ""); - - /** Checks in item, whether a private reservation for a given - * tag key. If so, a dictionary lookup is performed and the VR and private - * creator of the tag is updated correspondingly. - * @param item [in] The item to search in - * @param tag [in/out] The tag to be checked. Will be updated with VR and - * private creator. - * @param privateCreator [in] The private creator to check for (if known, - * can be left empty) - * @return Return EC_Normal if reservation checking and updating the - * tag was successful. Otherwise an error code is returned. - */ - static OFCondition checkPrivateTagReservation(DcmItem* item, - DcmTag& tag, - const OFString& privateCreator = ""); - - /** Function that allows for finding and/or inserting a hierarchy of items - * and attributes as defined by a path string; also returns a list of - * pointers for each successfully found or inserted paths. Every list - * contains pointers pointing to all the objects along the path - * starting from the object given as parameter. The pointer to the - * starting object will not be part of the result. - * - * In principle, the path string must have the following format (in - * arbitrary depth). Note that for searching a sequence, the example - * below would start with [ITEMNO] instead: - * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE - * . ITEMNO must be a positive integer starting with 0. - * SEQUENCE and ATTRIBUTE must be a tag, written e.g. - * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the - * path cannot be fully created (see option createIfNecessary), any - * possibly object changes are reverted. So a path is either fully created - * or no path component is created at all. The result can be obtained - * by calling the getResults() function. - * - * Example: The path - * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content - * Sequence in the given object, therein the 5th item, therein the "Concept - * Name Code Sequence" denoted by (0040,a043), therein the first item - * and finally therein the tag "Code Value". - * The resulting object list should (if success is returned) contain - * 1 result, consisting of a list with 5 pointers to 5 objects in the order - * in their logical order as they occur in the path string - * (in total 2 sequences, 2 items, and one leaf attribute). - * @param obj [in] The object to search (or create) a path in - * @param path [in] The path either starting with an attribute (either a - * sequence or a leaf attribute as a dictionary name or tag) or - * starting with an item - * @param createIfNecessary [in] If set, all missing objects found - * in the path string are created. If not set, - * only existing paths can be accessed and - * no new attribute or item is created. - * @return EC_Normal if successful, error code otherwise. - */ - OFCondition findOrCreatePath(DcmObject* obj, - const OFString& path, - OFBool createIfNecessary = OFFalse); - - /** Function that allows for deleting elements and items from - * a DICOM object tree. - * In principle, the path string must have the following format (in - * arbitrary depth). Note that for searching in a sequence, the example - * below would start with [ITEMNO] instead: - * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE - * . ITEMNO must be a positive integer starting with 0. - * SEQUENCE and ATTRIBUTE must be a tag, written e.g. - * "(0010,0010)" or as a dictionary name, e.g. "PatientName". - * - * Example: The path - * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content - * Sequence in the given object, therein the 5th item, therein the "Concept - * Name Code Sequence" denoted by (0040,a043), therein the first item - * and finally therein the tag "Code Value". Only "Code Value" will be - * deleted by the function. - * @param obj [in] The object to delete attribute or item from - * @param path [in] The path either starting with an attribute (either a - * sequence or a leaf attribute as a dictionary name or tag) or - * starting with an item - * @param numDeleted [out] Number of deleted attributes/items - * @return EC_Normal if successful, error code otherwise. If the desired - * attribute/item was not found, EC_TagNotFound is returned. - */ - OFCondition findOrDeletePath(DcmObject* obj, - const OFString& path, - Uint32& numDeleted); - - /** Returns the results from the search / creation call. - * @param searchResults [out] The resulting paths that were created/searched - * Note that the memory of the search results is freed - * automatically by the destructor and must not be freed - * by the caller. - * @return Number of results returned - */ - Uint32 getResults(OFList& searchResults); - - - /** Helper function that applies a specified "override key" in path syntax - * to the given dataset. The name "override" indicates that these keys have - * higher precedence than identical keys in a request dataset that might - * possibly read from a DICOM query file. - * @param dataset [in/out] the dataset (e.g.\ query keys) the override key is - * applied to. Must be non-NULL. - * @param overrideKey [in] the override key in path syntax (see class DcmPath). - * Also the path can end with a value assignment, e.g. - * "PatientName=Doe^John". An empty (or missing value) will - * not be ignored but will be written as empty to the - * attribute (if not a sequence or item). - * @return EC_Normal if adding was successful, error code otherwise - */ - OFCondition applyPathWithValue(DcmDataset* dataset, - const OFString& overrideKey); - - /** Destructor, cleans up memory that was allocated for any search results. - */ - ~DcmPathProcessor(); + /** Constructor, creates an empty search object. + */ + DcmPathProcessor(); + + /** Sets whether searching/creating paths will support wildcard for + * items. If set to false, any path operation with item wildcard characters + * will return an error. + * @param supported [in] If true, wildcard are enabled (default) + * If false, item wildcard support is disabled. + */ + void setItemWildcardSupport(const OFBool supported); + + /** Enables (class default: enabled) or disables checking of private + * reservations when inserting private tags. If enabled and a private + * tag is created that has no private reservation, an error is returned. + * If disabled, it is possible to insert private tags that do not have + * a reservation in the corresponding item/dataset. + * @param doChecking [in] OFTrue enables reservation checking, + * OFFalse disables it. + */ + void checkPrivateReservations(const OFBool doChecking); + + /** Returns private creator string for given tag + * @param item [in] The item to search in + * @param tagKey [in] The tag key for which a reservation should be looked up + * @param privateCreator [out] The private creator string + * @return Return EC_Normal if reservation was found (can be empty, though), + * EC_TagNotFound if no private creator tag exists, error otherwise + */ + static OFCondition getPrivateCreator(DcmItem* item, const DcmTagKey& tagKey, OFString& privateCreator); + + /** Checks in item, whether a private reservation for a given + * tag key exists. + * @param item [in] The item to search in + * @param tagKey [in/out] The tag to be checked. + * @param privateCreator [in] The private creator to check for (if known, + * can be left empty) + * @return Return EC_Normal if reservation checking was successful. + * Otherwise an error code is returned. + */ + static OFCondition + checkPrivateTagReservation(DcmItem* item, const DcmTagKey& tagKey, const OFString& privateCreator = ""); + + /** Checks in item, whether a private reservation for a given + * tag key. If so, a dictionary lookup is performed and the VR and private + * creator of the tag is updated correspondingly. + * @param item [in] The item to search in + * @param tag [in/out] The tag to be checked. Will be updated with VR and + * private creator. + * @param privateCreator [in] The private creator to check for (if known, + * can be left empty) + * @return Return EC_Normal if reservation checking and updating the + * tag was successful. Otherwise an error code is returned. + */ + static OFCondition checkPrivateTagReservation(DcmItem* item, DcmTag& tag, const OFString& privateCreator = ""); + + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). Note that for searching a sequence, the example + * below would start with [ITEMNO] instead: + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given object, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 5 pointers to 5 objects in the order + * in their logical order as they occur in the path string + * (in total 2 sequences, 2 items, and one leaf attribute). + * @param obj [in] The object to search (or create) a path in + * @param path [in] The path either starting with an attribute (either a + * sequence or a leaf attribute as a dictionary name or tag) or + * starting with an item + * @param createIfNecessary [in] If set, all missing objects found + * in the path string are created. If not set, + * only existing paths can be accessed and + * no new attribute or item is created. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreatePath(DcmObject* obj, const OFString& path, OFBool createIfNecessary = OFFalse); + + /** Function that allows for deleting elements and items from + * a DICOM object tree. + * In principle, the path string must have the following format (in + * arbitrary depth). Note that for searching in a sequence, the example + * below would start with [ITEMNO] instead: + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given object, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". Only "Code Value" will be + * deleted by the function. + * @param obj [in] The object to delete attribute or item from + * @param path [in] The path either starting with an attribute (either a + * sequence or a leaf attribute as a dictionary name or tag) or + * starting with an item + * @param numDeleted [out] Number of deleted attributes/items + * @return EC_Normal if successful, error code otherwise. If the desired + * attribute/item was not found, EC_TagNotFound is returned. + */ + OFCondition findOrDeletePath(DcmObject* obj, const OFString& path, Uint32& numDeleted); + + /** Returns the results from the search / creation call. + * @param searchResults [out] The resulting paths that were created/searched + * Note that the memory of the search results is freed + * automatically by the destructor and must not be freed + * by the caller. + * @return Number of results returned + */ + Uint32 getResults(OFList& searchResults); + + /** Helper function that applies a specified "override key" in path syntax + * to the given dataset. The name "override" indicates that these keys have + * higher precedence than identical keys in a request dataset that might + * possibly read from a DICOM query file. + * @param dataset [in/out] the dataset (e.g.\ query keys) the override key is + * applied to. Must be non-NULL. + * @param overrideKey [in] the override key in path syntax (see class DcmPath). + * Also the path can end with a value assignment, e.g. + * "PatientName=Doe^John". An empty (or missing value) will + * not be ignored but will be written as empty to the + * attribute (if not a sequence or item). + * @return EC_Normal if adding was successful, error code otherwise + */ + OFCondition applyPathWithValue(DcmDataset* dataset, const OFString& overrideKey); + + /** Destructor, cleans up memory that was allocated for any search results. + */ + ~DcmPathProcessor(); protected: - - /** Function that allows for finding and/or inserting a hierarchy of items - * and attributes as defined by a path string; also returns a list of - * pointers for each successfully found or inserted paths. Every list - * contains pointers pointing to all the objects along the path - * starting from the object given as parameter. The pointer to the - * starting object will not be part of the result. - * - * In principle, the path string must have the following format (in - * arbitrary depth). - * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE - * . ITEMNO must be a positive integer starting with 0. - * SEQUENCE and ATTRIBUTE must be a tag, written e.g. - * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the - * path cannot be fully created (see option createIfNecessary), any - * possibly object changes are reverted. So a path is either fully created - * or no path component is created at all. The result can be obtained - * by calling the getResults() function. - * - * Example: The path - * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content - * Sequence in the given item, therein the 5th item, therein the "Concept - * Name Code Sequence" denoted by (0040,a043), therein the first item - * and finally therein the tag "Code Value". - * The resulting object list should (if success is returned) contain - * 1 result, consisting of a list with 5 pointers to 5 objects in the order - * in their logical order as they occur in the path string - * (in total 2 sequences, 2 items, and one leaf attribute). - * @param item [in] The object to search (or create) a path in - * @param path [in] The path starting with an attribute (either a - * sequence or a leaf attribute) as a dictionary name or tag. - * The parsed attribute is removed from the path string. - * @return EC_Normal if successful, error code otherwise. - */ - OFCondition findOrCreateItemPath(DcmItem* item, - OFString& path); - - /** Function that allows for finding and/or inserting a hierarchy of items - * and attributes as defined by a path string; also returns a list of - * pointers for each successfully found or inserted paths. Every list - * contains pointers pointing to all the objects along the path - * starting from the object given as parameter. The pointer to the - * starting object will not be part of the result. - * - * In principle, the path string must have the following format (in - * arbitrary depth). - * [ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE - * . ITEMNO must be a positive integer starting with 0. - * SEQUENCE and ATTRIBUTE must be a tag, written e.g. - * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the - * path cannot be fully created (see option createIfNecessary), any - * possibly object changes are reverted. So a path is either fully created - * or no path component is created at all. The result can be obtained - * by calling the getResults() function. - * - * Example: The path - * "[4].(0040,a043)[0].CodeValue" selects the 5th item in the given - * sequence, therein the "Concept Name Code Sequence" denoted by - * (0040,a043), therein the first item and finally therein the - * tag "Code Value". - * The resulting object list should (if success is returned) contain - * 1 result, consisting of a list with 4 pointers to 4 objects in the order - * in their logical order as they occur in the path string - * (in total 1 sequence, 2 items, and one leaf element). - * @param seq [in] The object to search (or create) a path in - * @param path [in] The path starting with an item. The parsed item number - * (e.g. "[0]") is removed from the path string. - * @return EC_Normal if successful, error code otherwise. - */ - OFCondition findOrCreateSequencePath(DcmSequenceOfItems* seq, - OFString& path); - - /** Helper function that looks at the last node in a given path and deletes - * the corresponding DICOM object. Does not delete the path node itself: - * That is done by the calling function, findOrCreateItemPath(). - * @param objSearchedIn [in/out] The object the given path starts in. - * @param path [in/out] The complete path to the DICOM object to delete - * @param toDelete [in/out] The path node to delete. This node must be - * identical to the last node in the path parameter. Also - * the node must represent a DICOM sequence or leaf element, - * not an item. However, because it is isolated already by - * the calling function, it is provided here for convenience. - */ - static OFCondition deleteLastElemFromPath(DcmObject* objSearchedIn, - DcmPath* path, - DcmPathNode* toDelete); - - /** Helper function that looks at the last node in a given path and deletes - * the corresponding DICOM object. Does not delete the path node itself: - * That is done by the calling function, findOrCreateItemPath(). - * @param objSearchedIn [in/out] The object the given path starts in. - * @param path [in/out] The complete path to the DICOM object to delete - * @param toDelete [in/out] The path node to delete. This node must be - * identical to the last node in the path parameter. Also - * the node must represent a DICOM item, not a sequence - * However, because it is isolated already by the calling - * function, it is provided here for convenience. - */ - static OFCondition deleteLastItemFromPath(DcmObject* objSearchedIn, - DcmPath* path, - DcmPathNode* toDelete); - - /** Returns the private reservation tag key for a given private tag - * @param privateKey [in] The private key to calculate reservation tag for - * @return The reservation key. If given key is not private or an error, - * return DCM_UndefinedTagKey. If the given key is a reservation - * itself, it is directly returned. - */ - static DcmTagKey calcPrivateReservationTag(const DcmTagKey& privateKey); - - /** Cleans up memory that was allocated for any search results. - * Called when a new search is started or during object destruction. - * The DICOM data all freed paths and path nodes point to, is not - * touched, i.e. all memory to the DICOM objects pointed to must be - * freed from outside. Processing options like checking for private - * reservations and so on are not reset to default values but - * keep valid. - */ - void clear(); + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given item, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 5 pointers to 5 objects in the order + * in their logical order as they occur in the path string + * (in total 2 sequences, 2 items, and one leaf attribute). + * @param item [in] The object to search (or create) a path in + * @param path [in] The path starting with an attribute (either a + * sequence or a leaf attribute) as a dictionary name or tag. + * The parsed attribute is removed from the path string. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreateItemPath(DcmItem* item, OFString& path); + + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). + * [ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "[4].(0040,a043)[0].CodeValue" selects the 5th item in the given + * sequence, therein the "Concept Name Code Sequence" denoted by + * (0040,a043), therein the first item and finally therein the + * tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 4 pointers to 4 objects in the order + * in their logical order as they occur in the path string + * (in total 1 sequence, 2 items, and one leaf element). + * @param seq [in] The object to search (or create) a path in + * @param path [in] The path starting with an item. The parsed item number + * (e.g. "[0]") is removed from the path string. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreateSequencePath(DcmSequenceOfItems* seq, OFString& path); + + /** Helper function that looks at the last node in a given path and deletes + * the corresponding DICOM object. Does not delete the path node itself: + * That is done by the calling function, findOrCreateItemPath(). + * @param objSearchedIn [in/out] The object the given path starts in. + * @param path [in/out] The complete path to the DICOM object to delete + * @param toDelete [in/out] The path node to delete. This node must be + * identical to the last node in the path parameter. Also + * the node must represent a DICOM sequence or leaf element, + * not an item. However, because it is isolated already by + * the calling function, it is provided here for convenience. + * @return EC_Normal if successful, error otherwise + */ + static OFCondition deleteLastElemFromPath(DcmObject* objSearchedIn, DcmPath* path, DcmPathNode* toDelete); + + /** Helper function that looks at the last node in a given path and deletes + * the corresponding DICOM object. Does not delete the path node itself: + * That is done by the calling function, findOrCreateItemPath(). + * @param objSearchedIn [in/out] The object the given path starts in. + * @param path [in/out] The complete path to the DICOM object to delete + * @param toDelete [in/out] The path node to delete. This node must be + * identical to the last node in the path parameter. Also + * the node must represent a DICOM item, not a sequence + * However, because it is isolated already by the calling + * function, it is provided here for convenience. + * @return EC_Normal if successful, error otherwise + */ + static OFCondition deleteLastItemFromPath(DcmObject* objSearchedIn, DcmPath* path, DcmPathNode* toDelete); + + /** Returns the private reservation tag key for a given private tag + * @param privateKey [in] The private key to calculate reservation tag for + * @return The reservation key. If given key is not private or an error, + * return DCM_UndefinedTagKey. If the given key is a reservation + * itself, it is directly returned. + */ + static DcmTagKey calcPrivateReservationTag(const DcmTagKey& privateKey); + + /** Cleans up memory that was allocated for any search results. + * Called when a new search is started or during object destruction. + * The DICOM data all freed paths and path nodes point to, is not + * touched, i.e. all memory to the DICOM objects pointed to must be + * freed from outside. Processing options like checking for private + * reservations and so on are not reset to default values but + * keep valid. + */ + void clear(); private: - - /// Internal list that is during search for keeping track of current path - OFList m_currentPath; - - /// Internal list that represents the search results found - OFList m_results; - - /// Denotes whether missing items/sequences/attributes should be - /// automatically inserted when using findAndCreate routines - OFBool m_createIfNecessary; - - /// If enabled (default), any insertions of private tags will fail, if no - /// corresponding reservation exists in the underlying item - OFBool m_checkPrivateReservations; - - /// Denotes, whether a path is accepted that contains wildcards. - /// If false, then any search containing wildcards will return an error. - OFBool m_itemWildcardsEnabled; - - /** Private undefined copy constructor - */ - DcmPathProcessor(const DcmPathProcessor& rhs); - - /** Private undefined assignment operator - */ - DcmPathProcessor& operator=(const DcmPathProcessor& arg); + /// Internal list that is during search for keeping track of current path + OFList m_currentPath; + + /// Internal list that represents the search results found + OFList m_results; + + /// Denotes whether missing items/sequences/attributes should be + /// automatically inserted when using findAndCreate routines + OFBool m_createIfNecessary; + + /// If enabled (default), any insertions of private tags will fail, if no + /// corresponding reservation exists in the underlying item + OFBool m_checkPrivateReservations; + + /// Denotes, whether a path is accepted that contains wildcards. + /// If false, then any search containing wildcards will return an error. + OFBool m_itemWildcardsEnabled; + + /** Private undefined copy constructor + * @param rhs Object to copy from + */ + DcmPathProcessor(const DcmPathProcessor& rhs); + + /** Private undefined assignment operator + * @param arg Object to copy from + * @return Reference to this object + */ + DcmPathProcessor& operator=(const DcmPathProcessor& arg); }; - #endif // DCPATH_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcpixel.h b/dcmdata/include/dcmtk/dcmdata/dcpixel.h index 3235f9d2..c6dccc02 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcpixel.h +++ b/dcmdata/include/dcmtk/dcmdata/dcpixel.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -341,10 +341,7 @@ public: virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, const E_TransferSyntax oldXfer); - /** returns length of representation conforming to the - * transfer syntax with tag, vr, ... It does not create a - * representation. If no conforming representation exists an - * error code is set and 0 returned. + /** @copydoc DcmObject::calcElementLength() */ virtual Uint32 calcElementLength(const E_TransferSyntax xfer, const E_EncodingType enctype); @@ -400,6 +397,14 @@ public: virtual OFCondition writeXML(STD_NAMESPACE ostream &out, const size_t flags = 0); + /** write object in JSON format to a stream + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format); + /** special write method for creation of digital signatures * @param outStream DICOM output stream * @param oxfer output transfer syntax diff --git a/dcmdata/include/dcmtk/dcmdata/dcrleccd.h b/dcmdata/include/dcmtk/dcmdata/dcrleccd.h index 435c7bfb..77155b32 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcrleccd.h +++ b/dcmdata/include/dcmtk/dcmdata/dcrleccd.h @@ -47,6 +47,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -54,7 +58,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -104,6 +109,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -112,7 +121,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -126,6 +136,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -135,7 +149,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmdata/include/dcmtk/dcmdata/dcrlecce.h b/dcmdata/include/dcmtk/dcmdata/dcrlecce.h index 2b983240..4e36cea1 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcrlecce.h +++ b/dcmdata/include/dcmtk/dcmdata/dcrlecce.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2011, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -49,6 +49,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -56,7 +60,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -106,6 +111,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -114,7 +123,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -128,6 +138,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -137,7 +151,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmdata/include/dcmtk/dcmdata/dcsequen.h b/dcmdata/include/dcmtk/dcmdata/dcsequen.h index 62efe130..36a490b0 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcsequen.h +++ b/dcmdata/include/dcmtk/dcmdata/dcsequen.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -207,21 +207,7 @@ public: const Uint32 subPadlen = 0, Uint32 instanceLength = 0); - /** calculate the length of this DICOM element when encoded with the - * given transfer syntax and the given encoding type for sequences. - * For elements, the length includes the length of the tag, length field, - * VR field and the value itself, for items and sequences it returns - * the length of the complete item or sequence including delimitation tags - * if applicable. - * If length encoding is set to be explicit and the total sequence size is - * larger than the available 32-bit length field, then undefined length - * is returned. If "dcmWriteOversizedSeqsAndItemsUndefined" is disabled, - * also the internal DcmObject errorFlag is set to EC_SeqOrItemContentOverflow - * in case the sequence content (excluding tag header etc.) is already too - * large. - * @param xfer transfer syntax for length calculation - * @param enctype sequence encoding type for length calculation - * @return length of DICOM element + /** @copydoc DcmObject::calcElementLength() */ virtual Uint32 calcElementLength(const E_TransferSyntax xfer, const E_EncodingType enctype); diff --git a/dcmdata/include/dcmtk/dcmdata/dcuid.h b/dcmdata/include/dcmtk/dcmdata/dcuid.h index 7a6fafe5..16207a4a 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcuid.h +++ b/dcmdata/include/dcmtk/dcmdata/dcuid.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -369,6 +369,12 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_HEVCMain10ProfileLevel5_1TransferSyntax "1.2.840.10008.1.2.4.108" /// RLE Lossless #define UID_RLELosslessTransferSyntax "1.2.840.10008.1.2.5" +/// SMPTE ST 2110-20 Uncompressed Progressive Active Video +#define UID_SMPTEST2110_20_UncompressedProgressiveActiveVideoTransferSyntax "1.2.840.10008.1.2.7.1" +/// SMPTE ST 2110-20 Uncompressed Interlaced Active Video +#define UID_SMPTEST2110_20_UncompressedInterlacedActiveVideoTransferSyntax "1.2.840.10008.1.2.7.2" +/// SMPTE ST 2110-30 PCM Digital Audio +#define UID_SMPTEST2110_30_PCMDigitalAudioTransferSyntax "1.2.840.10008.1.2.7.3" /** RFC 2557 MIME Encapsulation (RETIRED) was only a pseudo transfer syntax used * to refer to MIME encapsulated HL7 CDA documents from a DICOMDIR when stored @@ -433,6 +439,12 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_GeneralAudioWaveformStorage "1.2.840.10008.5.1.4.1.1.9.4.2" #define UID_ArterialPulseWaveformStorage "1.2.840.10008.5.1.4.1.1.9.5.1" #define UID_RespiratoryWaveformStorage "1.2.840.10008.5.1.4.1.1.9.6.1" +#define UID_MultichannelRespiratoryWaveformStorage "1.2.840.10008.5.1.4.1.1.9.6.2" +#define UID_RoutineScalpElectroencephalogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.1" +#define UID_ElectromyogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.2" +#define UID_ElectrooculogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.3" +#define UID_SleepElectroencephalogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.4" +#define UID_BodyPositionWaveformStorage "1.2.840.10008.5.1.4.1.1.9.8.1" #define UID_RETIRED_StandaloneModalityLUTStorage "1.2.840.10008.5.1.4.1.1.10" #define UID_RETIRED_StandaloneVOILUTStorage "1.2.840.10008.5.1.4.1.1.11" #define UID_GrayscaleSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.1" @@ -487,6 +499,7 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_OphthalmicOpticalCoherenceTomographyEnFaceImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.7" #define UID_OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage "1.2.840.10008.5.1.4.1.1.77.1.5.8" #define UID_VLWholeSlideMicroscopyImageStorage "1.2.840.10008.5.1.4.1.1.77.1.6" +#define UID_DermoscopicPhotographyImageStorage "1.2.840.10008.5.1.4.1.1.77.1.7" #define UID_RETIRED_VLMultiframeImageStorage "1.2.840.10008.5.1.4.1.1.77.2" #define UID_LensometryMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.1" #define UID_AutorefractionMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.2" @@ -522,6 +535,8 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_EncapsulatedPDFStorage "1.2.840.10008.5.1.4.1.1.104.1" #define UID_EncapsulatedCDAStorage "1.2.840.10008.5.1.4.1.1.104.2" #define UID_EncapsulatedSTLStorage "1.2.840.10008.5.1.4.1.1.104.3" +#define UID_EncapsulatedOBJStorage "1.2.840.10008.5.1.4.1.1.104.4" +#define UID_EncapsulatedMTLStorage "1.2.840.10008.5.1.4.1.1.104.5" #define UID_PositronEmissionTomographyImageStorage "1.2.840.10008.5.1.4.1.1.128" #define UID_LegacyConvertedEnhancedPETImageStorage "1.2.840.10008.5.1.4.1.1.128.1" #define UID_RETIRED_StandalonePETCurveStorage "1.2.840.10008.5.1.4.1.1.129" @@ -543,6 +558,13 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_RTSegmentAnnotationStorage "1.2.840.10008.5.1.4.1.1.481.11" #define UID_RTRadiationSetStorage "1.2.840.10008.5.1.4.1.1.481.12" #define UID_CArmPhotonElectronRadiationStorage "1.2.840.10008.5.1.4.1.1.481.13" +#define UID_TomotherapeuticRadiationStorage "1.2.840.10008.5.1.4.1.1.481.14" +#define UID_RoboticArmRadiationStorage "1.2.840.10008.5.1.4.1.1.481.15" +#define UID_RTRadiationRecordSetStorage "1.2.840.10008.5.1.4.1.1.481.16" +#define UID_RTRadiationSalvageRecordStorage "1.2.840.10008.5.1.4.1.1.481.17" +#define UID_TomotherapeuticRadiationRecordStorage "1.2.840.10008.5.1.4.1.1.481.18" +#define UID_CArmPhotonElectronRadiationRecordStorage "1.2.840.10008.5.1.4.1.1.481.19" +#define UID_RoboticRadiationRecordStorage "1.2.840.10008.5.1.4.1.1.481.20" #define UID_RTBeamsDeliveryInstructionStorage "1.2.840.10008.5.1.4.34.7" #define UID_RTBrachyApplicationSetupDeliveryInstructionStorage "1.2.840.10008.5.1.4.34.10" #define UID_HangingProtocolStorage "1.2.840.10008.5.1.4.38.1" @@ -604,6 +626,7 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_UnifiedProcedureStepWatchSOPClass "1.2.840.10008.5.1.4.34.6.2" #define UID_UnifiedProcedureStepPullSOPClass "1.2.840.10008.5.1.4.34.6.3" #define UID_UnifiedProcedureStepEventSOPClass "1.2.840.10008.5.1.4.34.6.4" +#define UID_UnifiedProcedureStepQuerySOPClass "1.2.840.10008.5.1.4.34.6.5" #define UID_UPSGlobalSubscriptionSOPInstance "1.2.840.10008.5.1.4.34.5" #define UID_UPSFilteredGlobalSubscriptionSOPInstance "1.2.840.10008.5.1.4.34.5.1" @@ -618,6 +641,7 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_MOVEHangingProtocolInformationModel "1.2.840.10008.5.1.4.38.3" // Relevant Patient Information Query +#define UID_RelevantPatientInformationQuery_Prefix "1.2.840.10008.5.1.4.37." #define UID_GeneralRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.1" #define UID_BreastImagingRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.2" #define UID_CardiacRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.3" @@ -711,6 +735,12 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_DisplaySystemSOPClass "1.2.840.10008.5.1.1.40" #define UID_DisplaySystemSOPInstance "1.2.840.10008.5.1.1.40.1" +// Real-Time Video +#define UID_VideoEndoscopicImageRealTimeCommunication "1.2.840.10008.10.1" +#define UID_VideoPhotographicImageRealTimeCommunication "1.2.840.10008.10.2" +#define UID_AudioWaveformRealTimeCommunication "1.2.840.10008.10.3" +#define UID_RenditionSelectionDocumentRealTimeCommunication "1.2.840.10008.10.4" + // Other #define UID_VerificationSOPClass "1.2.840.10008.1.1" #define UID_RETIRED_BasicStudyContentNotificationSOPClass "1.2.840.10008.1.9" @@ -793,6 +823,12 @@ DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID #define UID_ICBM452T1FrameOfReference "1.2.840.10008.1.4.2.1" #define UID_ICBMSingleSubjectMRIFrameOfReference "1.2.840.10008.1.4.2.2" #define UID_IEC61217FixedCoordinateSystemFrameOfReference "1.2.840.10008.1.4.3.1" +#define UID_StandardRoboticCoordinateSystemFrameOfReference "1.2.840.10008.1.4.3.2" +#define UID_SRI24FrameOfReference "1.2.840.10008.1.4.4.1" +#define UID_Colin27FrameOfReference "1.2.840.10008.1.4.5.1" +#define UID_LPBA40AIRFrameOfReference "1.2.840.10008.1.4.6.1" +#define UID_LPBA40FLIRTFrameOfReference "1.2.840.10008.1.4.6.2" +#define UID_LPBA40SPM5FrameOfReference "1.2.840.10008.1.4.6.3" // Well-known SOP Instances for Color Palettes #define UID_HotIronColorPaletteSOPInstance "1.2.840.10008.1.5.1" diff --git a/dcmdata/include/dcmtk/dcmdata/dcvr.h b/dcmdata/include/dcmtk/dcmdata/dcvr.h index a643392b..f7584a75 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvr.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -221,6 +221,9 @@ enum DcmEVR /// OB or OW depending on context EVR_ox, + /// OB or OW, interpreted as pixel data (compressed or uncompressed) + EVR_px, + /// SS or US depending on context EVR_xs, diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrat.h b/dcmdata/include/dcmtk/dcmdata/dcvrat.h index 17d046d8..d86a0c07 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrat.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrat.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -159,7 +159,7 @@ class DCMTK_DCMDATA_EXPORT DcmAttributeTag * @param format used to format and customize the output * @return status, EC_Normal if successful, an error code otherwise */ - OFCondition writeJson(STD_NAMESPACE ostream &out, + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); /** get particular tag value diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrds.h b/dcmdata/include/dcmtk/dcmdata/dcvrds.h index f7ea5006..14d4a100 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrds.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrds.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2016, OFFIS e.V. + * Copyright (C) 1994-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -128,6 +128,30 @@ class DCMTK_DCMDATA_EXPORT DcmDecimalString const unsigned long pos, OFBool normalize = OFTrue); + /** put particular float value at a specific position. Precision (number of digits + * in fractional part) is 6. However, trailing zeroes from fractional part will be removed + * in every case. + * @param val the floating point value to put + * @param pos index where to put the value (0..vm-1) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat64(const Float64 val, + const unsigned long pos = 0); + + /** put particular float value at a specific position, using a particular + * precision (number of digits in fractional part). + * @param val the floating point value to put + * @param pos index where to put the value (0..vm-1) + * @param prec precision to be used, i.e. maximum number of fractional digits. + * Value should be 0 < prec < 15 (positive val) or 0 < prec < 14 (negative). + * @param cutTrailZeroes If OFTrue, any trailing non-significant zeroes are removed (from fraction). + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat64Prec(const Float64 val, + const unsigned long pos = 0, + const Uint8 prec = 6, + const OFBool cutTrailZeroes = OFTrue); + /** write object in XML format * @param out output stream to which the XML document is written * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrfd.h b/dcmdata/include/dcmtk/dcmdata/dcvrfd.h index 737447c0..c656a6d6 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrfd.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrfd.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,9 @@ #include "dcmtk/dcmdata/dcelem.h" +// forward declarations +class DcmJsonFormat; + /** a class representing the DICOM value representation 'Floating Point Double' (FD) */ @@ -214,6 +217,14 @@ class DCMTK_DCMDATA_EXPORT DcmFloatingPointDouble virtual OFBool matches(const DcmElement& candidate, const OFBool enableWildCardMatching = OFTrue) const; + /** write object in JSON format + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format); + protected: /** constructor. Create new element from given tag and length. diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrfl.h b/dcmdata/include/dcmtk/dcmdata/dcvrfl.h index fc4756cb..65e59c0e 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrfl.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrfl.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,8 @@ #include "dcmtk/dcmdata/dcelem.h" +// forward declarations +class DcmJsonFormat; /** a class representing the DICOM value representation 'Floating Point Single' (FL) */ @@ -216,6 +218,14 @@ class DCMTK_DCMDATA_EXPORT DcmFloatingPointSingle virtual OFBool matches(const DcmElement& candidate, const OFBool enableWildCardMatching = OFTrue) const; + /** write object in JSON format + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format); + protected: /** constructor. Create new element from given tag and length. diff --git a/dcmdata/include/dcmtk/dcmdata/dcvris.h b/dcmdata/include/dcmtk/dcmdata/dcvris.h index 3854f1d6..0fb0e51e 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvris.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvris.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2017, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -133,7 +133,7 @@ class DCMTK_DCMDATA_EXPORT DcmIntegerString * @param format used to format and customize the output * @return status, EC_Normal if successful, an error code otherwise */ - OFCondition writeJson(STD_NAMESPACE ostream &out, + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); }; diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrpn.h b/dcmdata/include/dcmtk/dcmdata/dcvrpn.h index 751f29a8..21ff617e 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrpn.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrpn.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2017, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -183,7 +183,7 @@ class DCMTK_DCMDATA_EXPORT DcmPersonName * @param format used to format and customize the output * @return status, EC_Normal if successful, an error code otherwise */ - OFCondition writeJson(STD_NAMESPACE ostream &out, + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format); /* --- static helper functions --- */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrsv.h b/dcmdata/include/dcmtk/dcmdata/dcvrsv.h index ae81fe66..8c88f092 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvrsv.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvrsv.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -209,6 +209,14 @@ class DCMTK_DCMDATA_EXPORT DcmSigned64bitVeryLong */ virtual OFCondition verify(const OFBool autocorrect = OFFalse); + /** write object in JSON format + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format); + protected: /** constructor. Create new element from given tag and length. diff --git a/dcmdata/include/dcmtk/dcmdata/dcvruv.h b/dcmdata/include/dcmtk/dcmdata/dcvruv.h index 04db9bd8..407f7e65 100644 --- a/dcmdata/include/dcmtk/dcmdata/dcvruv.h +++ b/dcmdata/include/dcmtk/dcmdata/dcvruv.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,7 +27,6 @@ #include "dcmtk/dcmdata/dcelem.h" - /** a class representing the DICOM value representation 'Unsigned 64-bit Very Long' (UV) */ class DCMTK_DCMDATA_EXPORT DcmUnsigned64bitVeryLong @@ -209,6 +208,14 @@ class DCMTK_DCMDATA_EXPORT DcmUnsigned64bitVeryLong */ virtual OFCondition verify(const OFBool autocorrect = OFFalse); + /** write object in JSON format + * @param out output stream to which the JSON document is written + * @param format used to format and customize the output + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format); + protected: /** constructor. Create new element from given tag and length. diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h index cb1fb08a..abc92a18 100644 --- a/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2011, OFFIS e.V. + * Copyright (C) 2001-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -43,6 +43,8 @@ public: * @param inputPlug - [in] The input plugin to read pixel data * @param outPlug - [in] The output plugin for specific SOP class output * @param resultDset - [out] The DICOM object resulting from the conversion + * The dataset is allocated in this method and must be freed by the + * caller. * @param proposedTS - [out] The proposed transfer syntax (needed e. g. * by JPEG input plugin) * @return EC_Normal, if successfull, error otherwise diff --git a/dcmdata/libi2d/i2djpgs.cc b/dcmdata/libi2d/i2djpgs.cc index 8a65fed0..0c966a44 100644 --- a/dcmdata/libi2d/i2djpgs.cc +++ b/dcmdata/libi2d/i2djpgs.cc @@ -826,30 +826,34 @@ OFCondition I2DJpegSource::skipVariable() OFCondition I2DJpegSource::isJPEGEncodingSupported(const E_JPGMARKER& jpegEncoding) const { + OFCondition result; DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Checking whether JPEG encoding is supported"); DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Encoding: " << jpegMarkerToString(jpegEncoding)); switch (jpegEncoding) { case E_JPGMARKER_SOF0: // Baseline - return EC_Normal; + result = EC_Normal; + break; case E_JPGMARKER_SOF1: // Extended sequential if (!m_disableExtSeqTs) - return EC_Normal; + result = EC_Normal; else - return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Extended sequential JPEG coding found but support disabled"); + result = makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Extended sequential JPEG coding found but support disabled"); + break; case E_JPGMARKER_SOF2: // Progressive if (!m_disableProgrTs) - return EC_Normal; + result = EC_Normal; else - return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Progressive JPEG coding found but disabled"); + result = makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Progressive JPEG coding found but disabled"); + break; // SOF3: Lossless, SOF5-7: Hierarchical (differential), SOF9-15: Arithmetic coding, all other default: OFString errMsg("JPEG data with encoding: '"); errMsg += jpegMarkerToString(jpegEncoding); errMsg += "' not supported"; - return makeOFCondition(OFM_dcmdata, 18, OF_error, errMsg.c_str()); + result = makeOFCondition(OFM_dcmdata, 18, OF_error, errMsg.c_str()); } - return EC_Normal; + return result; } diff --git a/dcmdata/libsrc/dcbytstr.cc b/dcmdata/libsrc/dcbytstr.cc index b8fa0b1c..3d550bde 100644 --- a/dcmdata/libsrc/dcbytstr.cc +++ b/dcmdata/libsrc/dcbytstr.cc @@ -475,6 +475,91 @@ OFCondition DcmByteString::putString(const char *stringVal, } +OFCondition DcmByteString::putOFStringAtPos(const OFString& stringVal, + const unsigned long pos) +{ + OFCondition result; + // Get old value + OFString str; + result = getOFStringArray( str ); + if (result.good()) + { + size_t currentVM = getNumberOfValues(); + // Trivial case: No values are set and new value should go to first position + if ( (currentVM == 0) && (pos == 0)) + return putOFStringArray(stringVal); + + // 1st case: Insert at the end + // If we insert at a position that does not yet exist, append missing number of components by + // adding the corresponding number of backspace chars, append new float value and return. + size_t futureVM = pos + 1; + if (futureVM > currentVM) + { + str = str.append(currentVM == 0 ? futureVM - currentVM - 1 : futureVM - currentVM, '\\'); + str = str.append(stringVal); + return putOFStringArray(str); + } + + // 2nd case: New value should be at position 0 + size_t rightPos = 0; + if (pos == 0) + { + // First value is empty: Insert new value + if (str[0] == '\\') + { + str = str.insert(0, stringVal); + } + // First value is set: Replace old value with new value + else + { + rightPos = str.find_first_of('\\', 0); + str = str.replace(0, rightPos, stringVal); + } + return putOFStringArray(str); + } + + // 3rd case: New value should be inserted somewhere in the middle + size_t leftPos = 0; + size_t vmPos = 0; + // First, find the correct position, and then insert / replace new value + do + { + // Step from value to value by looking for delimiters. + // Special handling first search (start looking at position 0 instead of 1) + if (vmPos == 0) leftPos = str.find('\\', 0); + else leftPos = str.find('\\', leftPos + 1 ); + // leftPos = str.find('\\', leftPos == 0 ? 0 : leftPos +1); + if (leftPos != OFString_npos) + { + vmPos++; + } + } + while ( (leftPos != OFString_npos) && (vmPos != pos) ); + rightPos = str.find_first_of('\\', leftPos+1); + if (rightPos == OFString_npos) rightPos = str.length(); + + // If we do not have an old value of size 1 or we have an empty value + if (rightPos - leftPos == 1) + { + // Empty value + if (str.at(leftPos) == '\\') + str = str.insert(rightPos, stringVal); + // Old value (length 1) + else + str = str.replace(leftPos, 1, stringVal); + } + // Otherwise replace existing old value (length > 1) + else + { + str = str.replace(leftPos+1, rightPos - leftPos, stringVal); + } + // Finally re-insert all values include new value + result = putOFStringArray( str ); + } + return result; +} + + // ******************************** diff --git a/dcmdata/libsrc/dccodec.cc b/dcmdata/libsrc/dccodec.cc index bb32f388..52d6a2a7 100644 --- a/dcmdata/libsrc/dccodec.cc +++ b/dcmdata/libsrc/dccodec.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2016, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -434,7 +434,8 @@ OFCondition DcmCodecList::decode( const DcmRepresentationParameter * fromParam, DcmPixelSequence * fromPixSeq, DcmPolymorphOBOW& uncompressedPixelData, - DcmStack & pixelStack) + DcmStack & pixelStack, + OFBool& removeOldRep) { #ifdef WITH_THREADS if (! codecLock.initialized()) return EC_IllegalCall; // should never happen @@ -454,7 +455,7 @@ OFCondition DcmCodecList::decode( { if ((*first)->codec->canChangeCoding(fromXfer, EXS_LittleEndianExplicit)) { - result = (*first)->codec->decode(fromParam, fromPixSeq, uncompressedPixelData, (*first)->codecParameter, pixelStack); + result = (*first)->codec->decode(fromParam, fromPixSeq, uncompressedPixelData, (*first)->codecParameter, pixelStack, removeOldRep); first = last; } else ++first; } @@ -513,7 +514,8 @@ OFCondition DcmCodecList::encode( const E_TransferSyntax toRepType, const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, - DcmStack & pixelStack) + DcmStack & pixelStack, + OFBool& removeOldRep) { toPixSeq = NULL; #ifdef WITH_THREADS @@ -535,7 +537,7 @@ OFCondition DcmCodecList::encode( { if (!toRepParam) toRepParam = (*first)->defaultRepParam; result = (*first)->codec->encode(fromRepType, fromParam, fromPixSeq, - toRepParam, toPixSeq, (*first)->codecParameter, pixelStack); + toRepParam, toPixSeq, (*first)->codecParameter, pixelStack, removeOldRep); first = last; } else ++first; } @@ -553,7 +555,8 @@ OFCondition DcmCodecList::encode( const E_TransferSyntax toRepType, const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, - DcmStack & pixelStack) + DcmStack & pixelStack, + OFBool& removeOldRep) { toPixSeq = NULL; #ifdef WITH_THREADS @@ -575,7 +578,7 @@ OFCondition DcmCodecList::encode( { if (!toRepParam) toRepParam = (*first)->defaultRepParam; result = (*first)->codec->encode(pixelData, length, toRepParam, toPixSeq, - (*first)->codecParameter, pixelStack); + (*first)->codecParameter, pixelStack, removeOldRep); first = last; } else ++first; } diff --git a/dcmdata/libsrc/dcdatset.cc b/dcmdata/libsrc/dcdatset.cc index 3b8a3dd1..3128b47c 100644 --- a/dcmdata/libsrc/dcdatset.cc +++ b/dcmdata/libsrc/dcdatset.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -343,21 +343,7 @@ OFCondition DcmDataset::writeXML(STD_NAMESPACE ostream &out, OFCondition DcmDataset::writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format) { - // write dataset content - if (!elementList->empty()) - { - elementList->seek(ELP_first); - OFCondition status = EC_Normal; - // write content of all children - status = elementList->get()->writeJson(out, format); - while (status.good() && elementList->seek(ELP_next)) - { - out << "," << format.newline(); - status = elementList->get()->writeJson(out, format); - } - return status; - } - return EC_Normal; + return writeJsonExt(out, format, OFFalse, OFFalse); // omit braces } diff --git a/dcmdata/libsrc/dcddirif.cc b/dcmdata/libsrc/dcddirif.cc index da285853..8937cbe3 100644 --- a/dcmdata/libsrc/dcddirif.cc +++ b/dcmdata/libsrc/dcddirif.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2019, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -697,7 +697,13 @@ static E_DirRecType sopClassToRecordType(const OFString &sopClass) compare(sopClass, UID_BasicVoiceAudioWaveformStorage) || compare(sopClass, UID_GeneralAudioWaveformStorage) || compare(sopClass, UID_ArterialPulseWaveformStorage) || - compare(sopClass, UID_RespiratoryWaveformStorage)) + compare(sopClass, UID_RespiratoryWaveformStorage) || + compare(sopClass, UID_RoutineScalpElectroencephalogramWaveformStorage) || + compare(sopClass, UID_ElectromyogramWaveformStorage) || + compare(sopClass, UID_ElectrooculogramWaveformStorage) || + compare(sopClass, UID_SleepElectroencephalogramWaveformStorage) || + compare(sopClass, UID_MultichannelRespiratoryWaveformStorage) || + compare(sopClass, UID_BodyPositionWaveformStorage)) { result = ERT_Waveform; } @@ -734,7 +740,9 @@ static E_DirRecType sopClassToRecordType(const OFString &sopClass) result = ERT_Spectroscopy; else if (compare(sopClass, UID_EncapsulatedPDFStorage) || compare(sopClass, UID_EncapsulatedCDAStorage) || - compare(sopClass, UID_EncapsulatedSTLStorage)) + compare(sopClass, UID_EncapsulatedSTLStorage) || + compare(sopClass, UID_EncapsulatedOBJStorage) || + compare(sopClass, UID_EncapsulatedMTLStorage)) { result = ERT_EncapDoc; } @@ -782,7 +790,14 @@ static E_DirRecType sopClassToRecordType(const OFString &sopClass) else if (compare(sopClass, UID_RTPhysicianIntentStorage) || compare(sopClass, UID_RTSegmentAnnotationStorage) || compare(sopClass, UID_RTRadiationSetStorage) || - compare(sopClass, UID_CArmPhotonElectronRadiationStorage)) + compare(sopClass, UID_CArmPhotonElectronRadiationStorage) || + compare(sopClass, UID_TomotherapeuticRadiationStorage) || + compare(sopClass, UID_RoboticArmRadiationStorage) || + compare(sopClass, UID_RTRadiationRecordSetStorage) || + compare(sopClass, UID_RTRadiationSalvageRecordStorage) || + compare(sopClass, UID_TomotherapeuticRadiationRecordStorage) || + compare(sopClass, UID_CArmPhotonElectronRadiationRecordStorage) || + compare(sopClass, UID_RoboticRadiationRecordStorage)) { result = ERT_Radiotherapy; } @@ -1605,7 +1620,13 @@ OFCondition DicomDirInterface::checkSOPClassAndXfer(DcmMetaInfo *metainfo, compare(mediaSOPClassUID, UID_BasicVoiceAudioWaveformStorage) || compare(mediaSOPClassUID, UID_GeneralAudioWaveformStorage) || compare(mediaSOPClassUID, UID_ArterialPulseWaveformStorage) || - compare(mediaSOPClassUID, UID_RespiratoryWaveformStorage); + compare(mediaSOPClassUID, UID_RespiratoryWaveformStorage) || + compare(mediaSOPClassUID, UID_MultichannelRespiratoryWaveformStorage) || + compare(mediaSOPClassUID, UID_RoutineScalpElectroencephalogramWaveformStorage) || + compare(mediaSOPClassUID, UID_ElectromyogramWaveformStorage) || + compare(mediaSOPClassUID, UID_ElectrooculogramWaveformStorage) || + compare(mediaSOPClassUID, UID_SleepElectroencephalogramWaveformStorage) || + compare(mediaSOPClassUID, UID_BodyPositionWaveformStorage); } /* is it one of the presentation state SOP Classes? */ if (!found) @@ -2577,16 +2598,22 @@ OFCondition DicomDirInterface::checkMandatoryAttributes(DcmMetaInfo *metainfo, OFString tmpString; if (compare(getStringFromDataset(dataset, DCM_VerificationFlag, tmpString), "VERIFIED")) { - /* VerificationDateTime is required if verification flag is VERIFIED, - retrieve most recent (= last) entry from VerifyingObserverSequence */ - DcmItem *ditem = NULL; - OFCondition l_status = dataset->findAndGetSequenceItem(DCM_VerifyingObserverSequence, ditem, -1 /*last*/); - if (l_status.good()) + if (checkExistsWithValue(dataset, DCM_VerifyingObserverSequence, filename)) { - if (!checkExistsWithValue(ditem, DCM_VerificationDateTime, filename)) - result = EC_MissingAttribute; + /* VerificationDateTime is required if VerificationFlag is VERIFIED, + retrieve most recent (= last) entry from VerifyingObserverSequence */ + DcmItem *ditem = NULL; + if (dataset->findAndGetSequenceItem(DCM_VerifyingObserverSequence, ditem, -1 /*last*/).good()) + { + if (!checkExistsWithValue(ditem, DCM_VerificationDateTime, filename)) + result = EC_MissingAttribute; + } else { + /* should never happen */ + DCMDATA_ERROR("INTERNAL ERROR: cannot get last item of VerifyingObserverSequence"); + result = EC_InternalError; + } } else - result = l_status; + result = EC_MissingAttribute; } } break; @@ -3300,7 +3327,7 @@ DcmDirectoryRecord *DicomDirInterface::buildStructReportRecord(DcmDirectoryRecor copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); if (compare(getStringFromDataset(dataset, DCM_VerificationFlag, tmpString), "VERIFIED")) { - /* VerificationDateTime is required if verification flag is VERIFIED, + /* VerificationDateTime is required if VerificationFlag is VERIFIED, retrieve most recent (= last) entry from VerifyingObserverSequence */ DcmItem *ditem = NULL; OFCondition status = dataset->findAndGetSequenceItem(DCM_VerifyingObserverSequence, ditem, -1 /*last*/); diff --git a/dcmdata/libsrc/dcdictbi.cc b/dcmdata/libsrc/dcdictbi.cc index e757906c..57e30a45 100644 --- a/dcmdata/libsrc/dcdictbi.cc +++ b/dcmdata/libsrc/dcdictbi.cc @@ -4,7 +4,7 @@ ** ** User: joergr ** Host: thinkpad -** Date: 2019-08-07 18:58:15 +** Date: 2020-11-24 14:49:53 ** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdictbi ** ** From: ../data/dicom.dic @@ -256,6 +256,46 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_AE, "ReceivingApplicationEntityTitle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0002, 0x0026, 0x0002, 0x0026, + EVR_UR, "SourcePresentationAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0027, 0x0002, 0x0027, + EVR_UR, "SendingPresentationAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0028, 0x0002, 0x0028, + EVR_UR, "ReceivingPresentationAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0031, 0x0002, 0x0031, + EVR_OB, "RTVMetaInformationVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0032, 0x0002, 0x0032, + EVR_UI, "RTVCommunicationSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0033, 0x0002, 0x0033, + EVR_UI, "RTVCommunicationSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0035, 0x0002, 0x0035, + EVR_OB, "RTVSourceIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0036, 0x0002, 0x0036, + EVR_OB, "RTVFlowIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0037, 0x0002, 0x0037, + EVR_UL, "RTVFlowRTPSamplingRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0038, 0x0002, 0x0038, + EVR_FD, "RTVFlowActualFrameDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0002, 0x0100, 0x0002, 0x0100, EVR_UI, "PrivateInformationCreatorUID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -384,6 +424,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, "AEGIS_DICOM_2.00" } #endif + , { 0x0006, 0x0001, 0x0006, 0x0001, + EVR_SQ, "CurrentFrameFunctionalGroupsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0008, 0x0001, 0x0008, 0x0001, EVR_UL, "RETIRED_LengthToEnd", 1, 1, "DICOM/retired", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -1160,6 +1204,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "AlternateRepresentationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0008, 0x3002, 0x0008, 0x3002, + EVR_UI, "AvailableTransferSyntaxUID", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0008, 0x3010, 0x0008, 0x3010, EVR_UI, "IrradiationEventUID", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -4196,6 +4244,26 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_IS, "GPSDifferential", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0016, 0x1001, 0x0016, 0x1001, + EVR_CS, "LightSourcePolarization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0016, 0x1002, 0x0016, 0x1002, + EVR_DS, "EmitterColorTemperature", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0016, 0x1003, 0x0016, 0x1003, + EVR_CS, "ContactMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0016, 0x1004, 0x0016, 0x1004, + EVR_CS, "ImmersionMedia", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0016, 0x1005, 0x0016, 0x1005, + EVR_DS, "OpticalMagnificationFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } #ifdef ENABLE_PRIVATE_TAGS , { 0x0017, 0x0000, 0x0017, 0x0000, EVR_LO, "ExtendedBodyPart", 1, 1, "PrivateTag", @@ -4459,7 +4527,7 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x100b, 0x0018, 0x100b, - EVR_UI, "ManufacturerDeviceClassUID", 1, -1, "DICOM/Supplement_175", + EVR_UI, "ManufacturerDeviceClassUID", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1010, 0x0018, 0x1010, @@ -5131,39 +5199,39 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1630, 0x0018, 0x1630, - EVR_CS, "OutlineShapeType", 1, 1, "DICOM/Supplement_175", + EVR_CS, "OutlineShapeType", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1631, 0x0018, 0x1631, - EVR_FD, "OutlineLeftVerticalEdge", 1, 1, "DICOM/Supplement_175", + EVR_FD, "OutlineLeftVerticalEdge", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1632, 0x0018, 0x1632, - EVR_FD, "OutlineRightVerticalEdge", 1, 1, "DICOM/Supplement_175", + EVR_FD, "OutlineRightVerticalEdge", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1633, 0x0018, 0x1633, - EVR_FD, "OutlineUpperHorizontalEdge", 1, 1, "DICOM/Supplement_175", + EVR_FD, "OutlineUpperHorizontalEdge", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1634, 0x0018, 0x1634, - EVR_FD, "OutlineLowerHorizontalEdge", 1, 1, "DICOM/Supplement_175", + EVR_FD, "OutlineLowerHorizontalEdge", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1635, 0x0018, 0x1635, - EVR_FD, "CenterOfCircularOutline", 2, 2, "DICOM/Supplement_175", + EVR_FD, "CenterOfCircularOutline", 2, 2, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1636, 0x0018, 0x1636, - EVR_FD, "DiameterOfCircularOutline", 1, 1, "DICOM/Supplement_175", + EVR_FD, "DiameterOfCircularOutline", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1637, 0x0018, 0x1637, - EVR_UL, "NumberOfPolygonalVertices", 1, 1, "DICOM/Supplement_175", + EVR_UL, "NumberOfPolygonalVertices", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1638, 0x0018, 0x1638, - EVR_OF, "VerticesOfThePolygonalOutline", 1, 1, "DICOM/Supplement_175", + EVR_OF, "VerticesOfThePolygonalOutline", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x0018, 0x1700, 0x0018, 0x1700, @@ -5310,6 +5378,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_LO, "TransducerData", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0018, 0x5011, 0x0018, 0x5011, + EVR_SQ, "TransducerIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0018, 0x5012, 0x0018, 0x5012, EVR_DS, "FocusDepth", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -18189,6 +18261,56 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_LT, "PatientStudyUID", 1, 1, "PrivateTag", DcmDictRange_Unspecified, DcmDictRange_Unspecified, "SIEMENS RIS" } +#endif + , { 0x0034, 0x0001, 0x0034, 0x0001, + EVR_SQ, "FlowIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0002, 0x0034, 0x0002, + EVR_OB, "FlowIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0003, 0x0034, 0x0003, + EVR_UI, "FlowTransferSyntaxUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0004, 0x0034, 0x0004, + EVR_UL, "FlowRTPSamplingRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0005, 0x0034, 0x0005, + EVR_OB, "SourceIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0007, 0x0034, 0x0007, + EVR_OB, "FrameOriginTimestamp", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0008, 0x0034, 0x0008, + EVR_CS, "IncludesImagingSubject", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x0009, 0x0034, 0x0009, + EVR_SQ, "FrameUsefulnessGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x000a, 0x0034, 0x000a, + EVR_SQ, "RealTimeBulkDataFlowSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x000b, 0x0034, 0x000b, + EVR_SQ, "CameraPositionGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x000c, 0x0034, 0x000c, + EVR_CS, "IncludesInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0034, 0x000d, 0x0034, 0x000d, + EVR_SQ, "TimeOfFrameGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS , { 0x0037, 0x0010, 0x0037, 0x0010, EVR_LO, "ReferringDepartment", 1, 1, "PrivateTag", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -18508,6 +18630,34 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_CS, "ChannelMode", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x003a, 0x0310, 0x003a, 0x0310, + EVR_UI, "MultiplexGroupUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0311, 0x003a, 0x0311, + EVR_DS, "PowerlineFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0312, 0x003a, 0x0312, + EVR_SQ, "ChannelImpedanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0313, 0x003a, 0x0313, + EVR_DS, "ImpedanceValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0314, 0x003a, 0x0314, + EVR_DT, "ImpedanceMeasurementDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0315, 0x003a, 0x0315, + EVR_DS, "ImpedanceMeasurementFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0316, 0x003a, 0x0316, + EVR_CS, "ImpedanceMeasurementCurrentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0040, 0x0001, 0x0040, 0x0001, EVR_AE, "ScheduledStationAETitle", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -19692,6 +19842,38 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "RETIRED_LanguageCodeSequenceTrial", 1, 1, "DICOM/retired", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0040, 0xa801, 0x0040, 0xa801, + EVR_SQ, "TabulatedValuesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa802, 0x0040, 0xa802, + EVR_UL, "NumberOfTableRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa803, 0x0040, 0xa803, + EVR_UL, "NumbeOfTableColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa804, 0x0040, 0xa804, + EVR_UL, "TableRowNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa805, 0x0040, 0xa805, + EVR_UL, "TableColumnNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa806, 0x0040, 0xa806, + EVR_SQ, "TableRowDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa807, 0x0040, 0xa807, + EVR_SQ, "TableColumnDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa808, 0x0040, 0xa808, + EVR_SQ, "CellValuesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0040, 0xa992, 0x0040, 0xa992, EVR_ST, "RETIRED_UniformResourceLocatorTrial", 1, 1, "DICOM/retired", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -22628,6 +22810,14 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "ModelUsageCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0068, 0x7004, 0x0068, 0x7004, + EVR_UI, "ModelGroupUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x7005, 0x0068, 0x7005, + EVR_UR, "RelativeURIReferenceWithinEncapsulatedDocument", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0070, 0x0001, 0x0070, 0x0001, EVR_SQ, "GraphicAnnotationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -23608,6 +23798,18 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "SelectorCodeSequenceValue", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x0072, 0x0081, 0x0072, 0x0081, + EVR_OV, "SelectorOVValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0082, 0x0072, 0x0082, + EVR_SV, "SelectorSVValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0083, 0x0072, 0x0083, + EVR_UV, "SelectorUVValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x0072, 0x0100, 0x0072, 0x0100, EVR_US, "NumberOfScreens", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -26191,15 +26393,15 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x3006, 0x00c9, 0x3006, 0x00c9, - EVR_SQ, "PatientLocationCoordinatesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientLocationCoordinatesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x3006, 0x00ca, 0x3006, 0x00ca, - EVR_SQ, "PatientLocationCoordinatesCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientLocationCoordinatesCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x3006, 0x00cb, 0x3006, 0x00cb, - EVR_SQ, "PatientSupportPositionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportPositionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x3008, 0x0010, 0x3008, 0x0010, @@ -26799,7 +27001,7 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0082, 0x300a, 0x0082, - EVR_DS, "BeamDoseSpecificationPoint", 3, 3, "DICOM", + EVR_DS, "RETIRED_BeamDoseSpecificationPoint", 3, 3, "DICOM/retired", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0083, 0x300a, 0x0083, @@ -28006,6 +28208,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_FL, "ScanningSpotSize", 2, 2, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x300a, 0x0399, 0x300a, 0x0399, + EVR_FL, "ScanSpotSizesDelivered", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x300a, 0x039a, 0x300a, 0x039a, EVR_IS, "NumberOfPaintings", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -28078,6 +28284,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_FL, "SourceToGeneralAccessoryDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x300a, 0x0426, 0x300a, 0x0426, + EVR_DS, "IsocenterToGeneralAccessoryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x300a, 0x0431, 0x300a, 0x0431, EVR_SQ, "ApplicatorGeometrySequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -28183,551 +28393,719 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0600, 0x300a, 0x0600, - EVR_US, "RTControlPointIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "RTControlPointIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0601, 0x300a, 0x0601, - EVR_US, "RadiationGenerationModeIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "RadiationGenerationModeIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0602, 0x300a, 0x0602, - EVR_US, "ReferencedDefinedDeviceIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedDefinedDeviceIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0603, 0x300a, 0x0603, - EVR_US, "RadiationDoseIdentificationIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "RadiationDoseIdentificationIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0604, 0x300a, 0x0604, - EVR_US, "NumberOfRTControlPoints", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfRTControlPoints", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0605, 0x300a, 0x0605, - EVR_US, "ReferencedRadiationGenerationModeIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedRadiationGenerationModeIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0606, 0x300a, 0x0606, - EVR_US, "TreatmentPositionIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "TreatmentPositionIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0607, 0x300a, 0x0607, - EVR_US, "ReferencedDeviceIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedDeviceIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0608, 0x300a, 0x0608, - EVR_LO, "TreatmentPositionGroupLabel", 1, 1, "DICOM/Supplement_175", + EVR_LO, "TreatmentPositionGroupLabel", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0609, 0x300a, 0x0609, - EVR_UI, "TreatmentPositionGroupUID", 1, 1, "DICOM/Supplement_175", + EVR_UI, "TreatmentPositionGroupUID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060a, 0x300a, 0x060a, - EVR_SQ, "TreatmentPositionGroupSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "TreatmentPositionGroupSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060b, 0x300a, 0x060b, - EVR_US, "ReferencedTreatmentPositionIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedTreatmentPositionIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060c, 0x300a, 0x060c, - EVR_US, "ReferencedRadiationDoseIdentificationIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedRadiationDoseIdentificationIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060d, 0x300a, 0x060d, - EVR_FD, "RTAccessoryHolderWaterEquivalentThickness", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTAccessoryHolderWaterEquivalentThickness", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060e, 0x300a, 0x060e, - EVR_US, "ReferencedRTAccessoryHolderDeviceIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ReferencedRTAccessoryHolderDeviceIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x060f, 0x300a, 0x060f, - EVR_CS, "RTAccessoryHolderSlotExistenceFlag", 1, 1, "DICOM/Supplement_175", + EVR_CS, "RTAccessoryHolderSlotExistenceFlag", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0610, 0x300a, 0x0610, - EVR_SQ, "RTAccessoryHolderSlotSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTAccessoryHolderSlotSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0611, 0x300a, 0x0611, - EVR_LO, "RTAccessoryHolderSlotID", 1, 1, "DICOM/Supplement_175", + EVR_LO, "RTAccessoryHolderSlotID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0612, 0x300a, 0x0612, - EVR_FD, "RTAccessoryHolderSlotDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTAccessoryHolderSlotDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0613, 0x300a, 0x0613, - EVR_FD, "RTAccessorySlotDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTAccessorySlotDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0614, 0x300a, 0x0614, - EVR_SQ, "RTAccessoryHolderDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTAccessoryHolderDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0615, 0x300a, 0x0615, - EVR_LO, "RTAccessoryDeviceSlotID", 1, 1, "DICOM/Supplement_175", + EVR_LO, "RTAccessoryDeviceSlotID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0616, 0x300a, 0x0616, - EVR_SQ, "RTRadiationSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTRadiationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0617, 0x300a, 0x0617, - EVR_SQ, "RadiationDoseSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationDoseSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0618, 0x300a, 0x0618, - EVR_SQ, "RadiationDoseIdentificationSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationDoseIdentificationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0619, 0x300a, 0x0619, - EVR_LO, "RadiationDoseIdentificationLabel", 1, 1, "DICOM/Supplement_175", + EVR_LO, "RadiationDoseIdentificationLabel", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061a, 0x300a, 0x061a, - EVR_CS, "ReferenceDoseType", 1, 1, "DICOM/Supplement_175", + EVR_CS, "ReferenceDoseType", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061b, 0x300a, 0x061b, - EVR_CS, "PrimaryDoseValueIndicator", 1, 1, "DICOM/Supplement_175", + EVR_CS, "PrimaryDoseValueIndicator", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061c, 0x300a, 0x061c, - EVR_SQ, "DoseValuesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "DoseValuesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061d, 0x300a, 0x061d, - EVR_CS, "DoseValuePurpose", 1, -1, "DICOM/Supplement_175", + EVR_CS, "DoseValuePurpose", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061e, 0x300a, 0x061e, - EVR_FD, "ReferenceDosePointCoordinates", 3, 3, "DICOM/Supplement_175", + EVR_FD, "ReferenceDosePointCoordinates", 3, 3, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x061f, 0x300a, 0x061f, - EVR_SQ, "RadiationDoseValuesParametersSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationDoseValuesParametersSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0620, 0x300a, 0x0620, - EVR_SQ, "MetersetToDoseMappingSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "MetersetToDoseMappingSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0621, 0x300a, 0x0621, - EVR_SQ, "ExpectedInVivoMeasurementValuesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ExpectedInVivoMeasurementValuesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0622, 0x300a, 0x0622, - EVR_US, "ExpectedInVivoMeasurementValueIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "ExpectedInVivoMeasurementValueIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0623, 0x300a, 0x0623, - EVR_LO, "RadiationDoseInVivoMeasurementLabel", 1, 1, "DICOM/Supplement_175", + EVR_LO, "RadiationDoseInVivoMeasurementLabel", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0624, 0x300a, 0x0624, - EVR_FD, "RadiationDoseCentralAxisDisplacement", 2, 2, "DICOM/Supplement_175", + EVR_FD, "RadiationDoseCentralAxisDisplacement", 2, 2, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0625, 0x300a, 0x0625, - EVR_FD, "RadiationDoseValue", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationDoseValue", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0626, 0x300a, 0x0626, - EVR_FD, "RadiationDoseSourceToSkinDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationDoseSourceToSkinDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0627, 0x300a, 0x0627, - EVR_FD, "RadiationDoseMeasurementPointCoordinates", 3, 3, "DICOM/Supplement_175", + EVR_FD, "RadiationDoseMeasurementPointCoordinates", 3, 3, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0628, 0x300a, 0x0628, - EVR_FD, "RadiationDoseSourceToExternalContourDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationDoseSourceToExternalContourDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0629, 0x300a, 0x0629, - EVR_SQ, "RTToleranceSetSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTToleranceSetSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062a, 0x300a, 0x062a, - EVR_LO, "RTToleranceSetLabel", 1, 1, "DICOM/Supplement_175", + EVR_LO, "RTToleranceSetLabel", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062b, 0x300a, 0x062b, - EVR_SQ, "AttributeToleranceValuesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "AttributeToleranceValuesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062c, 0x300a, 0x062c, - EVR_FD, "ToleranceValue", 1, 1, "DICOM/Supplement_175", + EVR_FD, "ToleranceValue", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062d, 0x300a, 0x062d, - EVR_SQ, "PatientSupportPositionToleranceSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportPositionToleranceSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062e, 0x300a, 0x062e, - EVR_FD, "TreatmentTimeLimit", 1, 1, "DICOM/Supplement_175", + EVR_FD, "TreatmentTimeLimit", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x062f, 0x300a, 0x062f, - EVR_SQ, "CArmPhotonElectronControlPointSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "CArmPhotonElectronControlPointSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0630, 0x300a, 0x0630, - EVR_SQ, "ReferencedRTRadiationSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ReferencedRTRadiationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0631, 0x300a, 0x0631, - EVR_SQ, "ReferencedRTInstanceSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ReferencedRTInstanceSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0632, 0x300a, 0x0632, - EVR_SQ, "ReferencedRTPatientSetupSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ReferencedRTPatientSetupSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0634, 0x300a, 0x0634, - EVR_FD, "SourceToPatientSurfaceDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "SourceToPatientSurfaceDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0635, 0x300a, 0x0635, - EVR_SQ, "TreatmentMachineSpecialModeCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "TreatmentMachineSpecialModeCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0636, 0x300a, 0x0636, - EVR_US, "IntendedNumberOfFractions", 1, 1, "DICOM/Supplement_175", + EVR_US, "IntendedNumberOfFractions", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0637, 0x300a, 0x0637, - EVR_CS, "RTRadiationSetIntent", 1, 1, "DICOM/Supplement_175", + EVR_CS, "RTRadiationSetIntent", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0638, 0x300a, 0x0638, - EVR_CS, "RTRadiationPhysicalAndGeometricContentDetailFlag", 1, 1, "DICOM/Supplement_175", + EVR_CS, "RTRadiationPhysicalAndGeometricContentDetailFlag", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0639, 0x300a, 0x0639, - EVR_CS, "RTRecordFlag", 1, 1, "DICOM/Supplement_175", + EVR_CS, "RTRecordFlag", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063a, 0x300a, 0x063a, - EVR_SQ, "TreatmentDeviceIdentificationSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "TreatmentDeviceIdentificationSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063b, 0x300a, 0x063b, - EVR_SQ, "ReferencedRTPhysicianIntentSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ReferencedRTPhysicianIntentSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063c, 0x300a, 0x063c, - EVR_FD, "CumulativeMeterset", 1, 1, "DICOM/Supplement_175", + EVR_FD, "CumulativeMeterset", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063d, 0x300a, 0x063d, - EVR_FD, "DeliveryRate", 1, 1, "DICOM/Supplement_175", + EVR_FD, "DeliveryRate", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063e, 0x300a, 0x063e, - EVR_SQ, "DeliveryRateUnitSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "DeliveryRateUnitSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x063f, 0x300a, 0x063f, - EVR_SQ, "TreatmentPositionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "TreatmentPositionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0640, 0x300a, 0x0640, - EVR_FD, "RadiationSourceAxisDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationSourceAxisDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0641, 0x300a, 0x0641, - EVR_US, "NumberOfRTBeamLimitingDevices", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfRTBeamLimitingDevices", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0642, 0x300a, 0x0642, - EVR_FD, "RTBeamLimitingDeviceProximalDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTBeamLimitingDeviceProximalDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0643, 0x300a, 0x0643, - EVR_FD, "RTBeamLimitingDeviceDistalDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTBeamLimitingDeviceDistalDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0644, 0x300a, 0x0644, - EVR_SQ, "ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0645, 0x300a, 0x0645, - EVR_FD, "BeamsModifierOrientationAngle", 1, 1, "DICOM/Supplement_175", + EVR_FD, "BeamModifierOrientationAngle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0646, 0x300a, 0x0646, - EVR_SQ, "FixedRTBeamDelimiterDeviceSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "FixedRTBeamDelimiterDeviceSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0647, 0x300a, 0x0647, - EVR_SQ, "ParallelRTBeamDelimiterDeviceSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "ParallelRTBeamDelimiterDeviceSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0648, 0x300a, 0x0648, - EVR_US, "NumberOfParallelRTBeamDelimiters", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfParallelRTBeamDelimiters", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0649, 0x300a, 0x0649, - EVR_FD, "ParallelRTBeamDelimiterBoundaries", 2, -1, "DICOM/Supplement_175", + EVR_FD, "ParallelRTBeamDelimiterBoundaries", 2, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064a, 0x300a, 0x064a, - EVR_FD, "ParallelRTBeamDelimiterPositions", 2, -1, "DICOM/Supplement_175", + EVR_FD, "ParallelRTBeamDelimiterPositions", 2, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064b, 0x300a, 0x064b, - EVR_FD, "RTBeamLimitingDeviceOffset", 2, 2, "DICOM/Supplement_175", + EVR_FD, "RTBeamLimitingDeviceOffset", 2, 2, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064c, 0x300a, 0x064c, - EVR_SQ, "RTBeamDelimiterGeometrySequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTBeamDelimiterGeometrySequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064d, 0x300a, 0x064d, - EVR_SQ, "RTBeamLimitingDeviceDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTBeamLimitingDeviceDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064e, 0x300a, 0x064e, - EVR_CS, "ParallelRTBeamDelimiterOpeningMode", 1, 1, "DICOM/Supplement_175", + EVR_CS, "ParallelRTBeamDelimiterOpeningMode", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x064f, 0x300a, 0x064f, - EVR_CS, "ParallelRTBeamDelimiterLeafMountingSide", 1, -1, "DICOM/Supplement_175", + EVR_CS, "ParallelRTBeamDelimiterLeafMountingSide", 1, -1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0650, 0x300a, 0x0650, - EVR_UI, "PatientSetupUID", 1, 1, "DICOM/Supplement_175", + EVR_UI, "PatientSetupUID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0651, 0x300a, 0x0651, - EVR_SQ, "WedgeDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "WedgeDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0652, 0x300a, 0x0652, - EVR_FD, "RadiationBeamWedgeAngle", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamWedgeAngle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0653, 0x300a, 0x0653, - EVR_FD, "RadiationBeamWedgeThinEdgeDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamWedgeThinEdgeDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0654, 0x300a, 0x0654, - EVR_FD, "RadiationBeamEffectiveWedgeAngle", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamEffectiveWedgeAngle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0655, 0x300a, 0x0655, - EVR_US, "NumberOfWedgePositions", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfWedgePositions", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0656, 0x300a, 0x0656, - EVR_SQ, "RTBeamLimitingDeviceOpeningSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTBeamLimitingDeviceOpeningSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0657, 0x300a, 0x0657, - EVR_US, "NumberOfRTBeamLimitingDeviceOpenings", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfRTBeamLimitingDeviceOpenings", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0658, 0x300a, 0x0658, - EVR_SQ, "RadiationDosimeterUnitSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationDosimeterUnitSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0659, 0x300a, 0x0659, - EVR_SQ, "RTDeviceDistanceReferenceLocationCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RTDeviceDistanceReferenceLocationCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065a, 0x300a, 0x065a, - EVR_SQ, "RadiationDeviceConfigurationAndCommissioningKeySequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationDeviceConfigurationAndCommissioningKeySequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065b, 0x300a, 0x065b, - EVR_SQ, "PatientSupportPositionParameterSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportPositionParameterSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065c, 0x300a, 0x065c, - EVR_CS, "PatientSupportPositionSpecificationMethod", 1, 1, "DICOM/Supplement_175", + EVR_CS, "PatientSupportPositionSpecificationMethod", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065d, 0x300a, 0x065d, - EVR_SQ, "PatientSupportPositionDeviceParameterSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportPositionDeviceParameterSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065e, 0x300a, 0x065e, - EVR_US, "DeviceOrderIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "DeviceOrderIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x065f, 0x300a, 0x065f, - EVR_US, "PatientSupportPositionParameterOrderIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "PatientSupportPositionParameterOrderIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0660, 0x300a, 0x0660, - EVR_SQ, "PatientSupportPositionDeviceToleranceSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportPositionDeviceToleranceSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0661, 0x300a, 0x0661, - EVR_US, "PatientSupportPositionToleranceOrderIndex", 1, 1, "DICOM/Supplement_175", + EVR_US, "PatientSupportPositionToleranceOrderIndex", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0662, 0x300a, 0x0662, - EVR_SQ, "CompensatorDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "CompensatorDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0663, 0x300a, 0x0663, - EVR_CS, "CompensatorMapOrientation", 1, 1, "DICOM/Supplement_175", + EVR_CS, "CompensatorMapOrientation", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0664, 0x300a, 0x0664, - EVR_OF, "CompensatorProximalThicknessMap", 1, 1, "DICOM/Supplement_175", + EVR_OF, "CompensatorProximalThicknessMap", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0665, 0x300a, 0x0665, - EVR_OF, "CompensatorDistalThicknessMap", 1, 1, "DICOM/Supplement_175", + EVR_OF, "CompensatorDistalThicknessMap", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0666, 0x300a, 0x0666, - EVR_FD, "CompensatorBasePlaneOffset", 1, 1, "DICOM/Supplement_175", + EVR_FD, "CompensatorBasePlaneOffset", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0667, 0x300a, 0x0667, - EVR_SQ, "CompensatorShapeFabricationCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "CompensatorShapeFabricationCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0668, 0x300a, 0x0668, - EVR_SQ, "CompensatorShapeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "CompensatorShapeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0669, 0x300a, 0x0669, - EVR_FD, "RadiationBeamCompensatorMillingToolDiameter", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamCompensatorMillingToolDiameter", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066a, 0x300a, 0x066a, - EVR_SQ, "BlockDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "BlockDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066b, 0x300a, 0x066b, - EVR_OF, "BlockEdgeData", 1, 1, "DICOM/Supplement_175", + EVR_OF, "BlockEdgeData", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066c, 0x300a, 0x066c, - EVR_CS, "BlockOrientation", 1, 1, "DICOM/Supplement_175", + EVR_CS, "BlockOrientation", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066d, 0x300a, 0x066d, - EVR_FD, "RadiationBeamBlockThickness", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamBlockThickness", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066e, 0x300a, 0x066e, - EVR_FD, "RadiationBeamBlockSlabThickness", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RadiationBeamBlockSlabThickness", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x066f, 0x300a, 0x066f, - EVR_SQ, "BlockEdgeDataSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "BlockEdgeDataSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0670, 0x300a, 0x0670, - EVR_US, "NumberOfRTAccessoryHolders", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfRTAccessoryHolders", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0671, 0x300a, 0x0671, - EVR_SQ, "GeneralAccessoryDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "GeneralAccessoryDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0672, 0x300a, 0x0672, - EVR_US, "NumberOfGeneralAccessories", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfGeneralAccessories", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0673, 0x300a, 0x0673, - EVR_SQ, "BolusDefinitionSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "BolusDefinitionSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0674, 0x300a, 0x0674, - EVR_US, "NumberOfBoluses", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfBoluses", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0675, 0x300a, 0x0675, - EVR_UI, "EquipmentFrameOfReferenceUID", 1, 1, "DICOM/Supplement_175", + EVR_UI, "EquipmentFrameOfReferenceUID", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0676, 0x300a, 0x0676, - EVR_ST, "EquipmentFrameOfReferenceDescription", 1, 1, "DICOM/Supplement_175", + EVR_ST, "EquipmentFrameOfReferenceDescription", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0677, 0x300a, 0x0677, - EVR_SQ, "EquipmentReferencePointCoordinatesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "EquipmentReferencePointCoordinatesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0678, 0x300a, 0x0678, - EVR_SQ, "EquipmentReferencePointCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "EquipmentReferencePointCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0679, 0x300a, 0x0679, - EVR_FD, "RTBeamLimitingDeviceAngle", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTBeamLimitingDeviceAngle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067a, 0x300a, 0x067a, - EVR_FD, "SourceRollAngle", 1, 1, "DICOM/Supplement_175", + EVR_FD, "SourceRollAngle", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067b, 0x300a, 0x067b, - EVR_SQ, "RadiationGenerationModeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationGenerationModeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067c, 0x300a, 0x067c, - EVR_SH, "RadiationGenerationModeLabel", 1, 1, "DICOM/Supplement_175", + EVR_SH, "RadiationGenerationModeLabel", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067d, 0x300a, 0x067d, - EVR_ST, "RadiationGenerationModeDescription", 1, 1, "DICOM/Supplement_175", + EVR_ST, "RadiationGenerationModeDescription", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067e, 0x300a, 0x067e, - EVR_SQ, "RadiationGenerationModeMachineCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationGenerationModeMachineCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x067f, 0x300a, 0x067f, - EVR_SQ, "RadiationTypeCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationTypeCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0680, 0x300a, 0x0680, - EVR_DS, "NominalEnergy", 1, 1, "DICOM/Supplement_175", + EVR_DS, "NominalEnergy", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0681, 0x300a, 0x0681, - EVR_DS, "MinimumNominalEnergy", 1, 1, "DICOM/Supplement_175", + EVR_DS, "MinimumNominalEnergy", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0682, 0x300a, 0x0682, - EVR_DS, "MaximumNominalEnergy", 1, 1, "DICOM/Supplement_175", + EVR_DS, "MaximumNominalEnergy", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0683, 0x300a, 0x0683, - EVR_SQ, "RadiationFluenceModifierCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "RadiationFluenceModifierCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0684, 0x300a, 0x0684, - EVR_SQ, "EnergyUnitCodeSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "EnergyUnitCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0685, 0x300a, 0x0685, - EVR_US, "NumberOfRadiationGenerationModes", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfRadiationGenerationModes", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0686, 0x300a, 0x0686, - EVR_SQ, "PatientSupportDevicesSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "PatientSupportDevicesSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0687, 0x300a, 0x0687, - EVR_US, "NumberOfPatientSupportDevices", 1, 1, "DICOM/Supplement_175", + EVR_US, "NumberOfPatientSupportDevices", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0688, 0x300a, 0x0688, - EVR_FD, "RTBeamModifierDefinitionDistance", 1, 1, "DICOM/Supplement_175", + EVR_FD, "RTBeamModifierDefinitionDistance", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300a, 0x0689, 0x300a, 0x0689, - EVR_SQ, "BeamAreaLimitSequence", 1, 1, "DICOM/Supplement_175", + EVR_SQ, "BeamAreaLimitSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x068a, 0x300a, 0x068a, + EVR_SQ, "ReferencedRTPrescriptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0700, 0x300a, 0x0700, + EVR_UI, "TreatmentSessionUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0701, 0x300a, 0x0701, + EVR_CS, "RTRadiationUsage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0702, 0x300a, 0x0702, + EVR_SQ, "ReferencedRTRadiationSetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0703, 0x300a, 0x0703, + EVR_SQ, "ReferencedRTRadiationRecordSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0704, 0x300a, 0x0704, + EVR_US, "RTRadiationSetDeliveryNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0705, 0x300a, 0x0705, + EVR_US, "ClinicalFractionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0706, 0x300a, 0x0706, + EVR_CS, "RTTreatmentFractionCompletionStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0707, 0x300a, 0x0707, + EVR_CS, "RTRadiationSetUsage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0708, 0x300a, 0x0708, + EVR_CS, "TreatmentDeliveryContinuationFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0709, 0x300a, 0x0709, + EVR_CS, "TreatmentRecordContentOrigin", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0714, 0x300a, 0x0714, + EVR_CS, "RTTreatmentTerminationStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0715, 0x300a, 0x0715, + EVR_SQ, "RTTreatmentTerminationReasonCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0716, 0x300a, 0x0716, + EVR_SQ, "MachineSpecificTreatmentTerminationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0722, 0x300a, 0x0722, + EVR_SQ, "RTRadiationSalvageRecordControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0723, 0x300a, 0x0723, + EVR_CS, "StartingMetersetValueKnownFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0730, 0x300a, 0x0730, + EVR_ST, "TreatmentTerminationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0731, 0x300a, 0x0731, + EVR_SQ, "TreatmentToleranceViolationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0732, 0x300a, 0x0732, + EVR_CS, "TreatmentToleranceViolationCategory", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0733, 0x300a, 0x0733, + EVR_SQ, "TreatmentToleranceViolationAttributeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0734, 0x300a, 0x0734, + EVR_ST, "TreatmentToleranceViolationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0735, 0x300a, 0x0735, + EVR_ST, "TreatmentToleranceViolationIdentification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0736, 0x300a, 0x0736, + EVR_DT, "TreatmentToleranceViolationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x073a, 0x300a, 0x073a, + EVR_DT, "RecordedRTControlPointDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x073b, 0x300a, 0x073b, + EVR_US, "ReferencedRadiationRTControlPointIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x073e, 0x300a, 0x073e, + EVR_SQ, "AlternateValueSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x073f, 0x300a, 0x073f, + EVR_SQ, "ConfirmationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0740, 0x300a, 0x0740, + EVR_SQ, "InterlockSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0741, 0x300a, 0x0741, + EVR_DT, "InterlockDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0742, 0x300a, 0x0742, + EVR_ST, "InterlockDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0743, 0x300a, 0x0743, + EVR_SQ, "InterlockOriginatingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0744, 0x300a, 0x0744, + EVR_SQ, "InterlockCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0745, 0x300a, 0x0745, + EVR_SQ, "InterlockResolutionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0746, 0x300a, 0x0746, + EVR_SQ, "InterlockResolutionUserSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0760, 0x300a, 0x0760, + EVR_DT, "OverrideDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0761, 0x300a, 0x0761, + EVR_SQ, "TreatmentToleranceViolationTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0762, 0x300a, 0x0762, + EVR_SQ, "TreatmentToleranceViolationCauseCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0772, 0x300a, 0x0772, + EVR_SQ, "MeasuredMetersetToDoseMappingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0773, 0x300a, 0x0773, + EVR_US, "ReferencedExpectedInVivoMeasurementValueIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0774, 0x300a, 0x0774, + EVR_SQ, "DoseMeasurementDeviceCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0780, 0x300a, 0x0780, + EVR_SQ, "AdditionalParameterRecordingInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0783, 0x300a, 0x0783, + EVR_ST, "InterlockOriginDescription", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x300c, 0x0002, 0x300c, 0x0002, @@ -29066,6 +29444,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "DeviceTypeCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x3010, 0x002f, 0x3010, 0x002f, + EVR_SQ, "SegmentAnnotationTypeModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } , { 0x3010, 0x0030, 0x3010, 0x0030, EVR_SQ, "PatientEquipmentRelationshipCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, @@ -29418,6 +29800,54 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_SQ, "DeliveryTimeStructureCodeSequence", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } + , { 0x3010, 0x0089, 0x3010, 0x0089, + EVR_SQ, "TreatmentSiteModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0090, 0x3010, 0x0090, + EVR_CS, "RoboticBaseLocationIndicator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0091, 0x3010, 0x0091, + EVR_SQ, "RoboticPathNodeSetCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0092, 0x3010, 0x0092, + EVR_UL, "RoboticNodeIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0093, 0x3010, 0x0093, + EVR_FD, "RTTreatmentSourceCoordinates", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0094, 0x3010, 0x0094, + EVR_FD, "RadiationSourceCoordinateSystemYawAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0095, 0x3010, 0x0095, + EVR_FD, "RadiationSourceCoordinateSystemRollAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0096, 0x3010, 0x0096, + EVR_FD, "RadiationSourceCoordinateSystemPitchAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0097, 0x3010, 0x0097, + EVR_SQ, "RoboticPathControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0098, 0x3010, 0x0098, + EVR_SQ, "TomotherapeuticControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x0099, 0x3010, 0x0099, + EVR_FD, "TomotherapeuticLeafOpenDurations", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3010, 0x009a, 0x3010, 0x009a, + EVR_FD, "TomotherapeuticLeafInitialClosedDurations", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } #ifdef ENABLE_PRIVATE_TAGS , { 0x3f01, 0x0001, 0x3f01, 0x0001, EVR_LO, "InstitutionCode", 1, 1, "PrivateTag", @@ -29743,7 +30173,7 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x4010, 0x1029, 0x4010, 0x1029, - EVR_LO, "ThreatDetectionAlgorithmandVersion", 1, -1, "DICOM/DICOS", + EVR_LO, "ThreatDetectionAlgorithmAndVersion", 1, -1, "DICOM/DICOS", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x4010, 0x102a, 0x4010, 0x102a, @@ -30079,7 +30509,7 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x7fe0, 0x0010, 0x7fe0, 0x0010, - EVR_ox, "PixelData", 1, 1, "DICOM", + EVR_px, "PixelData", 1, 1, "DICOM", DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL } , { 0x7fe0, 0x0020, 0x7fe0, 0x0020, @@ -30107,6 +30537,10 @@ static const DBI_SimpleEntry simpleBuiltinDict[] = { EVR_ox, "PixelData", 1, 1, "PrivateTag", DcmDictRange_Unspecified, DcmDictRange_Unspecified, "SPI-P Release 1" } + , { 0x7fe1, 0x1060, 0x7fe1, 0x1060, + EVR_px, "IllegalPrivatePixelSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_Ultrasound_MovieGroup_001" } , { 0x7fe3, 0x0000, 0x7fe3, 0x0000, EVR_LT, "ImageGraphicsFormatCode", 1, 1, "PrivateTag", DcmDictRange_Unspecified, DcmDictRange_Unspecified, diff --git a/dcmdata/libsrc/dcelem.cc b/dcmdata/libsrc/dcelem.cc index 12dcf4c9..86f6f444 100644 --- a/dcmdata/libsrc/dcelem.cc +++ b/dcmdata/libsrc/dcelem.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -1176,7 +1176,7 @@ OFCondition DcmElement::read(DcmInputStream &inStream, { /* Return error code if we are are not ignoring parsing errors */ if (!dcmIgnoreParsingErrors.get()) - errorFlag = EC_StreamNotifyClient; + errorFlag = EC_StreamNotifyClient; // should we rather return EC_InvalidStream? /* In any case, make sure that calling the load value routine on this * element will fail later. For that, create the stream factory that * the load routine will use. Otherwise it would not realize @@ -1304,15 +1304,15 @@ OFCondition DcmElement::write(DcmOutputStream &outStream, if ((elemLength) > 0xffff && (! myvalidvr.usesExtendedLengthEncoding()) && outXfer.isExplicitVR()) { - /* special case: we are writing in explicit VR, the VR of this - * element uses a 2-byte length encoding, but the element length is - * too large for a 2-byte length field. We need to write this element - * as VR=UN (or VR=OB if the generation of UN is disabled). - * In this method, the variable "vr" is only used to determine the - * output byte order, which is always the same for OB and UN. - * Therefore, we do not need to distinguish between these two. - */ - vr = EVR_UN; + /* special case: we are writing in explicit VR, the VR of this + * element uses a 2-byte length encoding, but the element length is + * too large for a 2-byte length field. We need to write this element + * as VR=UN (or VR=OB if the generation of UN is disabled). + * In this method, the variable "vr" is only used to determine the + * output byte order, which is always the same for OB and UN. + * Therefore, we do not need to distinguish between these two. + */ + vr = EVR_UN; } /* In case the transfer state is not initialized, this is an illegal call */ @@ -1661,7 +1661,7 @@ void DcmElement::writeJsonOpener(STD_NAMESPACE ostream &out, /* write attribute tag */ out << ++format.indent() << "\"" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << tag.getGTag(); + << STD_NAMESPACE setw(4) << STD_NAMESPACE uppercase << tag.getGTag(); /* write "ggggeeee" (no comma, upper case!) */ /* for private element numbers, zero out 2 first element digits */ /* or output full element number "eeee" */ diff --git a/dcmdata/libsrc/dcencdoc.cc b/dcmdata/libsrc/dcencdoc.cc index d83430dc..f4655eaa 100644 --- a/dcmdata/libsrc/dcencdoc.cc +++ b/dcmdata/libsrc/dcencdoc.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2018-2019, OFFIS e.V. + * Copyright (C) 2018-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -13,7 +13,7 @@ * * Module: dcmdata * - * Author: Pedro Arizpe + * Author: Pedro ArizpeGomez * * Purpose: Implementation of Document encapsulation * @@ -46,59 +46,59 @@ #define EXITCODE_MEMORY_EXHAUSTED 4 DcmEncapsulatedDocument::DcmEncapsulatedDocument() : - opt_patientBirthdate(), - opt_patientID(), - opt_patientName(), - opt_patientSex(), + opt_patientBirthdate(), + opt_patientID(), + opt_patientName(), + opt_patientSex(), - opt_conceptCM(), - opt_conceptCSD(), - opt_conceptCV(), + opt_conceptCM(), + opt_conceptCSD(), + opt_conceptCV(), - opt_documentTitle(), - opt_seriesFile(), - opt_seriesUID(), - opt_studyUID(), + opt_documentTitle(), + opt_seriesFile(), + opt_seriesUID(), + opt_studyUID(), - opt_oenctype(EET_ExplicitLength), - opt_writeMode(EWM_fileformat), - opt_oglenc(EGL_withoutGL), - opt_opadenc(EPD_withoutPadding), - opt_oxfer(EXS_LittleEndianExplicit), - opt_filepad(0), - opt_itempad(0), + opt_oenctype(EET_ExplicitLength), + opt_writeMode(EWM_fileformat), + opt_oglenc(EGL_withoutGL), + opt_opadenc(EPD_withoutPadding), + opt_oxfer(EXS_LittleEndianExplicit), + opt_filepad(0), + opt_itempad(0), - opt_readSeriesInfo(OFFalse), - opt_annotation(OFTrue), - opt_increment(OFFalse), + opt_readSeriesInfo(OFFalse), + opt_annotation(OFTrue), + opt_increment(OFFalse), - opt_instance(1), - opt_overrideKeys(), + opt_instance(1), + opt_overrideKeys(), - cda_mediaTypes(), - hl7_InstanceIdentifier(), - opt_override(OFFalse), - // Frame of Reference Module (STL) - opt_frameOfReferenceUID(), - opt_positionReferenceIndicator(), - // Frame of Reference Module (STL) - opt_manufacturer(), - opt_manufacturerModelName(), - opt_deviceSerialNumber(), - opt_softwareVersions(), - // Enhanced General Equipment Module (STL) - opt_measurementUnitsCM(), - opt_measurementUnitsCSD(), - opt_measurementUnitsCV(), - //encapsulation file type - ftype() + cda_mediaTypes(), + hl7_InstanceIdentifier(), + opt_override(OFFalse), + // Frame of Reference Module (STL) + opt_frameOfReferenceUID(), + opt_positionReferenceIndicator(), + // Frame of Reference Module (STL) + opt_manufacturer(), + opt_manufacturerModelName(), + opt_deviceSerialNumber(), + opt_softwareVersions(), + // Enhanced General Equipment Module (STL) + opt_measurementUnitsCM(), + opt_measurementUnitsCSD(), + opt_measurementUnitsCV(), + //encapsulation file type + ftype() { } OFBool DcmEncapsulatedDocument::XMLsearchAttribute( - XMLNode currnode, - OFList *results, - OFString attr) + XMLNode currnode, + OFList *results, + OFString attr) { OFBool found = OFFalse; #ifndef _XMLWIDECHAR @@ -133,8 +133,8 @@ OFBool DcmEncapsulatedDocument::XMLsearchAttribute( } OFString DcmEncapsulatedDocument::XMLgetAllAttributeValues( - XMLNode fileNode, - OFString attr) + XMLNode fileNode, + OFString attr) { OFString attributeValues; #ifndef _XMLWIDECHAR @@ -168,8 +168,8 @@ OFString DcmEncapsulatedDocument::XMLgetAllAttributeValues( } OFString DcmEncapsulatedDocument::XMLgetAttribute( - XMLNode fileNode, - DcmTagKey attr) + XMLNode fileNode, + DcmTagKey attr) { OFString result = ""; #ifndef _XMLWIDECHAR @@ -182,9 +182,8 @@ OFString DcmEncapsulatedDocument::XMLgetAttribute( } if (attr == DCM_HL7InstanceIdentifier) { - result = OFString(OFSTRING_GUARD( - fileNode.getChildNode("id").getAttribute("root"))) + "^" + OFString(OFSTRING_GUARD( - fileNode.getChildNode("id").getAttribute("extension"))); + result = OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("root"))) + "^" + + OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("extension"))); } /*PatientNameExtension could reflect the type of name (PHON, IDE, ABC) if (attr == DCM_PatientNameExtension) @@ -193,25 +192,35 @@ OFString DcmEncapsulatedDocument::XMLgetAttribute( }*/ if (attr == DCM_PatientName) { - result = OFString(OFSTRING_GUARD( - fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/family").getText())) + "^" + OFString(OFSTRING_GUARD( - fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode("given", 0).getText())) + "^" + OFString(OFSTRING_GUARD( - fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode("given", 1).getText())) + "^" + OFString(OFSTRING_GUARD( - fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/prefix").getText())) + "^" + OFString(OFSTRING_GUARD( - fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/suffix").getText())); + result = OFString( + OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/family").getText())) + "^" + + OFString(OFSTRING_GUARD( + fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode( + "given", 0).getText())) + "^" + + OFString(OFSTRING_GUARD( + fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode( + "given", 1).getText())) + "^" + + OFString( + OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/prefix").getText())) + "^" + + OFString( + OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/suffix").getText())); } if (attr == DCM_PatientSex) { - result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/administrativeGenderCode").getAttribute("code"))); + result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath( + "recordTarget/patientRole/patient/administrativeGenderCode").getAttribute("code"))); } if (attr == DCM_PatientBirthDate) { - result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/birthTime").getAttribute("value"))); + result = OFString(OFSTRING_GUARD( + fileNode.getChildNodeByPath("recordTarget/patientRole/patient/birthTime").getAttribute( + "value"))); } //Table A.8-1. Basic Code Attributes Mapping to HL7 V3 Code Data Types (CV, CS, CE and CD) if (attr == DCM_PatientID) { - result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/id").getAttribute("extension"))); + result = OFString( + OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/id").getAttribute("extension"))); } if (attr == DCM_CodeValue)//Code Value { @@ -223,27 +232,27 @@ OFString DcmEncapsulatedDocument::XMLgetAttribute( } if (attr == DCM_CodingSchemeDesignator)//Coding Scheme Designator (0008,0102) { - OFString CSDtemp=OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemName"))); + OFString CSDtemp = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemName"))); // Abbreviate most common CSNs - if(CSDtemp==OFString("LOINC")) + if (CSDtemp == OFString("LOINC")) { - result = OFString("LN"); + result = OFString("LN"); } else { - if(CSDtemp==OFString("DICOM")) + if (CSDtemp == OFString("DICOM")) { - result = OFString("DC"); + result = OFString("DC"); } else { - if(CSDtemp==OFString("SNOMED")) + if (CSDtemp == OFString("SNOMED")) { result = OFString("SRT"); } else { - result=CSDtemp; + result = CSDtemp; } } } @@ -261,10 +270,11 @@ OFString DcmEncapsulatedDocument::XMLgetAttribute( } int DcmEncapsulatedDocument::getCDAData( - const char *filename, - OFLogger &appLogger) + const char *filename, + OFLogger &appLogger) { #ifdef _XMLWIDECHAR +#warning "DCMTK compiled with 'wide char XML parser'. cda2dcm will be unable to read and encapsulate CDA documents." OFLOG_ERROR(appLogger, "DCMTK compiled with \"wide char XML parser\". Cannot parse CDA data because of incompatible API."); return 99; #else @@ -299,16 +309,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "Patient ID mismatch:" << OFendl - << "Found in the CDA file : " << pID << OFendl - << "Entered (or found in DCM file): " << opt_patientID << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << pID << OFendl + << "Entered (or found in DCM file): " << opt_patientID << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } else { OFLOG_WARN(appLogger, "Patient ID mismatch:" << OFendl - << "Found in the CDA file : " << pID << OFendl - << "Provided (in DCM file): " << opt_patientID); + << "Found in the CDA file : " << pID << OFendl + << "Provided (in DCM file): " << opt_patientID); } } else @@ -324,15 +334,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "Patient Birth Date mismatch:" << OFendl - << "Found in the CDA file : " << pBirthDate << OFendl - << "Provided (in DCM file): " << opt_patientBirthdate << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << pBirthDate << OFendl + << "Provided (in DCM file): " << opt_patientBirthdate << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "Patient Birth Date mismatch:" << OFendl - << "Found in the CDA file : " << pBirthDate << OFendl - << "Provided (in DCM file): " << opt_patientBirthdate); + << "Found in the CDA file : " << pBirthDate << OFendl + << "Provided (in DCM file): " << opt_patientBirthdate); } } else opt_patientBirthdate = pBirthDate; @@ -345,15 +356,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "Patient Sex mismatch:" << OFendl - << "Found in the CDA file : " << pSex << OFendl - << "Provided (in DCM file): " << opt_patientSex << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << pSex << OFendl + << "Provided (in DCM file): " << opt_patientSex << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "Patient Sex mismatch:" << OFendl - << "Found in the CDA file : " << pSex << OFendl - << "Provided (in DCM file): " << opt_patientSex); + << "Found in the CDA file : " << pSex << OFendl + << "Provided (in DCM file): " << opt_patientSex); } } else opt_patientSex = pSex; @@ -366,15 +378,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "Patient Name mismatch:" << OFendl - << "Found in the CDA file : " << pName << OFendl - << "Provided (in DCM file): " << opt_patientName << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << pName << OFendl + << "Provided (in DCM file): " << opt_patientName << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "Patient Name mismatch:" << OFendl - << "Found in the CDA file : " << pName << OFendl - << "Provided (in DCM file): " << opt_patientName); + << "Found in the CDA file : " << pName << OFendl + << "Provided (in DCM file): " << opt_patientName); } } else opt_patientName = pName; @@ -395,15 +408,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "Document Title mismatch:" << OFendl - << "Found in the CDA file : " << dTitle << OFendl - << "Provided (in DCM file): " << opt_documentTitle << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << dTitle << OFendl + << "Provided (in DCM file): " << opt_documentTitle << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "Document Title mismatch:" << OFendl - << "Found in the CDA file : " << dTitle << OFendl - << "Provided (in DCM file): " << opt_documentTitle); + << "Found in the CDA file : " << dTitle << OFendl + << "Provided (in DCM file): " << opt_documentTitle); } } else opt_documentTitle = dTitle; @@ -417,15 +431,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "concept CSD mismatch:" << OFendl - << "Found in the CDA file : " << cCSD << OFendl - << "Provided (in DCM file): " << opt_conceptCSD << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << cCSD << OFendl + << "Provided (in DCM file): " << opt_conceptCSD << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "concept CSD mismatch:" << OFendl - << "Found in the CDA file : " << cCSD << OFendl - << "Provided (in DCM file): " << opt_conceptCSD); + << "Found in the CDA file : " << cCSD << OFendl + << "Provided (in DCM file): " << opt_conceptCSD); } } else opt_conceptCSD = cCSD; @@ -438,15 +453,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "concept CV mismatch:" << OFendl - << "Found in the CDA file : " << cCV << OFendl - << "Provided (in DCM file): " << opt_conceptCV << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << cCV << OFendl + << "Provided (in DCM file): " << opt_conceptCV << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "concept CV mismatch:" << OFendl - << "Found in the CDA file : " << cCV << OFendl - << "Provided (in DCM file): " << opt_conceptCV); + << "Found in the CDA file : " << cCV << OFendl + << "Provided (in DCM file): " << opt_conceptCV); } } else opt_conceptCV = cCV; @@ -459,15 +475,16 @@ int DcmEncapsulatedDocument::getCDAData( if (!opt_override) { OFLOG_ERROR(appLogger, "concept CM mismatch:" << OFendl - << "Found in the CDA file : " << cCM << OFendl - << "Provided (in DCM file): " << opt_conceptCM << OFendl - << "If you wish to override, run again with +ov"); + << "Found in the CDA file : " << cCM << OFendl + << "Provided (in DCM file): " << opt_conceptCM << OFendl + << "If you wish to override, run again with +ov"); return EXITCODE_COMMANDLINE_SYNTAX_ERROR; } - else { + else + { OFLOG_WARN(appLogger, "concept CM mismatch:" << OFendl - << "Found in the CDA file : " << cCM << OFendl - << "Provided (in DCM file): " << opt_conceptCM); + << "Found in the CDA file : " << cCM << OFendl + << "Provided (in DCM file): " << opt_conceptCM); } } else opt_conceptCM = cCM; @@ -481,13 +498,15 @@ void DcmEncapsulatedDocument::addCDACommandlineOptions(OFCommandLine &cmd) ftype = "cda"; cmd.setOptionColumns(LONGCOL, SHORTCOL); cmd.setParamColumn(LONGCOL + SHORTCOL + 4); - cmd.addParam( "cdafile-in", "CDA input filename to be converted"); - cmd.addParam( "dcmfile-out", "DICOM output filename"); + cmd.addParam("cdafile-in", "CDA input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); addGeneralOptions(cmd); addDocumentOptions(cmd); cmd.addSubGroup("override CDA data:"); - cmd.addOption("--no-override", "-ov", "CDA patient and document data must match study,\nseries or manually entered information (default)"); - cmd.addOption("--override", "+ov", "CDA's data will be overwritten by study, series\nor manually entered information"); + cmd.addOption("--no-override", "-ov", + "CDA patient and document data must match study,\nseries or manually entered information (default)"); + cmd.addOption("--override", "+ov", + "CDA's data will be overwritten by study, series\nor manually entered information"); addOutputOptions(cmd); } @@ -496,8 +515,8 @@ void DcmEncapsulatedDocument::addPDFCommandlineOptions(OFCommandLine &cmd) ftype = "pdf"; cmd.setOptionColumns(LONGCOL, SHORTCOL); cmd.setParamColumn(LONGCOL + SHORTCOL + 4); - cmd.addParam( "pdffile-in", "PDF input filename to be converted"); - cmd.addParam( "dcmfile-out", "DICOM output filename"); + cmd.addParam("pdffile-in", "PDF input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); addGeneralOptions(cmd); addDocumentOptions(cmd); addOutputOptions(cmd); @@ -508,93 +527,94 @@ void DcmEncapsulatedDocument::addSTLCommandlineOptions(OFCommandLine &cmd) ftype = "stl"; cmd.setOptionColumns(LONGCOL, SHORTCOL); cmd.setParamColumn(LONGCOL + SHORTCOL + 4); - cmd.addParam( "stlfile-in", "STL input filename to be converted"); - cmd.addParam( "dcmfile-out", "DICOM output filename"); + cmd.addParam("stlfile-in", "STL input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); addGeneralOptions(cmd); addDocumentOptions(cmd); cmd.addSubGroup("enhanced general equipment:"); - cmd.addOption("--manufacturer", "+mn", 1, "[n]ame: string", - "manufacturer's name"); - cmd.addOption("--manufacturer-model", "+mm", 1, "[n]ame: string", - "manufacturer's model name"); - cmd.addOption("--device-serial", "+ds", 1, "[n]umber: string", - "device serial number"); - cmd.addOption("--software-versions", "+sv", 1, "[v]ersions: string", - "software versions"); + cmd.addOption("--manufacturer", "+mn", 1, "[n]ame: string", + "manufacturer's name"); + cmd.addOption("--manufacturer-model", "+mm", 1, "[n]ame: string", + "manufacturer's model name"); + cmd.addOption("--device-serial", "+ds", 1, "[n]umber: string", + "device serial number"); + cmd.addOption("--software-versions", "+sv", 1, "[v]ersions: string", + "software versions"); cmd.addSubGroup("3d model measurement units:"); - cmd.addOption("--measurement-units", "+mu", 3, "[CSD] [CV] [CM]: string (default: UCUM, um, um)", - "measurement units defined by coding scheme\ndesignator CSD, code value CV, code meaning CM"); + cmd.addOption("--measurement-units", "+mu", 3, "[CSD] [CV] [CM]: string (default: UCUM, um, um)", + "measurement units defined by coding scheme\ndesignator CSD, code value CV, code meaning CM"); addOutputOptions(cmd); } void DcmEncapsulatedDocument::addGeneralOptions(OFCommandLine &cmd) { - cmd.addGroup( "general options:", LONGCOL, SHORTCOL + 2); - cmd.addOption( "--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); - cmd.addOption( "--version", "print version information and exit", OFCommandLine::AF_Exclusive); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); OFLog::addOptions(cmd); } void DcmEncapsulatedDocument::addDocumentOptions(OFCommandLine &cmd) { - cmd.addGroup( "DICOM document options:"); - cmd.addSubGroup("document title:"); - cmd.addOption("--title", "+t", 1, "[t]itle: string (default: empty)", - "document title"); - cmd.addOption("--concept-name", "+cn", 3, "[CSD] [CV] [CM]: string (default: empty)", - "coded representation of document title defined\nby coding scheme designator CSD,\ncode value CV and code meaning CM"); - cmd.addSubGroup("patient data:"); - cmd.addOption("--patient-name", "+pn", 1, "[n]ame: string", - "patient's name in DICOM PN syntax"); - cmd.addOption("--patient-id", "+pi", 1, "[i]d: string", - "patient identifier"); - cmd.addOption("--patient-birthdate", "+pb", 1, "[d]ate: string (YYYYMMDD)", - "patient's birth date"); - cmd.addOption("--patient-sex", "+ps", 1, "[s]ex: string (M, F or O)", - "patient's sex"); - cmd.addSubGroup("study and series:"); - cmd.addOption("--generate", "+sg", "generate new study and\nseries UIDs (default)"); - cmd.addOption("--study-from", "+st", 1, "[f]ilename: string", - "read patient/study data from DICOM file"); - cmd.addOption("--series-from", "+se", 1, "[f]ilename: string", - "read patient/study/series data from DICOM file"); - cmd.addSubGroup("instance number:"); - cmd.addOption("--instance-one", "+i1", "use instance number 1\n(default, not with +se)"); - cmd.addOption("--instance-inc", "+ii", "increment instance number (only with +se)"); - cmd.addOption("--instance-set", "+is", 1, "[i]nstance number: integer", "use instance number i"); - cmd.addSubGroup("burned-in annotation:"); - cmd.addOption("--annotation-yes", "+an", "document contains patient identifying data\n(default)"); - cmd.addOption("--annotation-no", "-an", "document does not contain patient identif. data"); + cmd.addGroup("DICOM document options:"); + cmd.addSubGroup("document title:"); + cmd.addOption("--title", "+t", 1, "[t]itle: string (default: empty)", + "document title"); + cmd.addOption("--concept-name", "+cn", 3, "[CSD] [CV] [CM]: string (default: empty)", + "coded representation of document title defined\nby coding scheme designator CSD,\n" + "code value CV and code meaning CM"); + cmd.addSubGroup("patient data:"); + cmd.addOption("--patient-name", "+pn", 1, "[n]ame: string", + "patient's name in DICOM PN syntax"); + cmd.addOption("--patient-id", "+pi", 1, "[i]d: string", + "patient identifier"); + cmd.addOption("--patient-birthdate", "+pb", 1, "[d]ate: string (YYYYMMDD)", + "patient's birth date"); + cmd.addOption("--patient-sex", "+ps", 1, "[s]ex: string (M, F or O)", + "patient's sex"); + cmd.addSubGroup("study and series:"); + cmd.addOption("--generate", "+sg", "generate new study and\nseries UIDs (default)"); + cmd.addOption("--study-from", "+st", 1, "[f]ilename: string", + "read patient/study data from DICOM file"); + cmd.addOption("--series-from", "+se", 1, "[f]ilename: string", + "read patient/study/series data from DICOM file"); + cmd.addSubGroup("instance number:"); + cmd.addOption("--instance-one", "+i1", "use instance number 1\n(default, not with +se)"); + cmd.addOption("--instance-inc", "+ii", "increment instance number (only with +se)"); + cmd.addOption("--instance-set", "+is", 1, "[i]nstance number: integer", "use instance number i"); + cmd.addSubGroup("burned-in annotation:"); + cmd.addOption("--annotation-yes", "+an", "document contains patient identifying data\n(default)"); + cmd.addOption("--annotation-no", "-an", "document does not contain patient identif. data"); } void DcmEncapsulatedDocument::addOutputOptions(OFCommandLine &cmd) { - cmd.addGroup( "processing options:"); - cmd.addSubGroup("other processing options:"); - cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"", - "add further attribute"); - cmd.addGroup( "output options:"); - cmd.addSubGroup("output transfer syntax:"); - cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)"); - cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); - cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); - cmd.addSubGroup("group length encoding:"); - cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); - cmd.addOption("--group-length-create", "+g", "always write with group length elements"); - cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); - cmd.addSubGroup("length encoding in sequences and items:"); - cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); - cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); - cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); - cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); - cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); - cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", - "align file on multiple of f bytes\nand items on multiple of i bytes"); + cmd.addGroup("processing options:"); + cmd.addSubGroup("other processing options:"); + cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"", + "add further attribute"); + cmd.addGroup("output options:"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); } void DcmEncapsulatedDocument::parseArguments( - OFConsoleApplication& app, - OFCommandLine& cmd) + OFConsoleApplication &app, + OFCommandLine &cmd) { //command line parameters and options cmd.getParam(1, opt_ifname); @@ -640,13 +660,13 @@ void DcmEncapsulatedDocument::parseArguments( { app.checkValue(cmd.getValue(opt_patientName)); app.checkConflict("--patient-name", "--study-from or --series-from", - opt_seriesFile != ""); + opt_seriesFile != ""); } if (cmd.findOption("--patient-id")) { app.checkValue(cmd.getValue(opt_patientID)); app.checkConflict("--patient-id", "--study-from or --series-from", - opt_seriesFile != ""); + opt_seriesFile != ""); } if (cmd.findOption("--patient-birthdate")) { @@ -715,14 +735,14 @@ void DcmEncapsulatedDocument::parseArguments( if (cmd.findOption("--padding-retain")) { app.checkConflict("--padding-retain", "--write-dataset", - opt_writeMode == EWM_dataset); + opt_writeMode == EWM_dataset); opt_opadenc = EPD_noChange; } if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; if (cmd.findOption("--padding-create")) { app.checkConflict("--padding-create", "--write-dataset", - opt_writeMode == EWM_dataset); + opt_writeMode == EWM_dataset); app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); opt_opadenc = EPD_withPadding; @@ -730,17 +750,18 @@ void DcmEncapsulatedDocument::parseArguments( cmd.endOptionBlock(); // create override attribute dataset (copied from findscu code) - if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft ) ) + if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft)) { const char *ovKey = NULL; - do { + do + { app.checkValue(cmd.getValue(ovKey)); overrideKeys.push_back(ovKey); - } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft ) ); + } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft)); } DcmEncapsulatedDocument::setOverrideKeys(overrideKeys); // initialize default for --series-from - if (opt_seriesFile!="" && opt_readSeriesInfo) opt_increment = OFTrue; + if (opt_seriesFile != "" && opt_readSeriesInfo) opt_increment = OFTrue; cmd.beginOptionBlock(); if (cmd.findOption("--instance-one")) @@ -764,7 +785,7 @@ void DcmEncapsulatedDocument::parseArguments( cmd.endOptionBlock(); } -OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger& appLogger) +OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger &appLogger) { char buf[100]; OFCondition cond = EC_Normal; @@ -776,7 +797,7 @@ OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger& appLogger) if (cond.bad()) { OFLOG_WARN(appLogger, cond.text() - << ": reading file: " << opt_seriesFile); + << ": reading file: " << opt_seriesFile); } else { @@ -788,28 +809,28 @@ OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger& appLogger) c = NULL; if (dset->findAndGetString(DCM_PatientName, c).good() && c) { - opt_patientName = c; + opt_patientName = c; } c = NULL; if (dset->findAndGetString(DCM_PatientID, c).good() && c) { - opt_patientID = c; + opt_patientID = c; } c = NULL; if (dset->findAndGetString(DCM_PatientBirthDate, c).good() && c) { - opt_patientBirthdate = c; + opt_patientBirthdate = c; } c = NULL; if (dset->findAndGetString(DCM_PatientSex, c).good() && c) { - opt_patientSex = c; + opt_patientSex = c; } OFLOG_TRACE(appLogger, "reading study attributes"); c = NULL; if (dset->findAndGetString(DCM_StudyInstanceUID, c).good() && c) { - opt_studyUID = c; + opt_studyUID = c; } OFLOG_TRACE(appLogger, "reading series attributes"); if (opt_readSeriesInfo) @@ -817,10 +838,10 @@ OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger& appLogger) c = NULL; if (dset->findAndGetString(DCM_SeriesInstanceUID, c).good() && c) { - opt_seriesUID = c; + opt_seriesUID = c; } if (dset->findAndGetSint32(DCM_InstanceNumber, - incrementedInstance).good()) + incrementedInstance).good()) { ++incrementedInstance; } @@ -888,8 +909,8 @@ OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger& appLogger) } int DcmEncapsulatedDocument::insertEncapsulatedDocument( - DcmItem *dataset, - OFLogger& appLogger) + DcmItem *dataset, + OFLogger &appLogger) { char buf[100]; size_t fileSize = 0; @@ -950,13 +971,13 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( if (!found) { OFLOG_ERROR(appLogger, "file " << opt_ifname - << ": unable to decode PDF version number"); + << ": unable to decode PDF version number"); fclose(encapfile); return EXITCODE_INVALID_INPUT_FILE; } OFLOG_INFO(appLogger, "file " << opt_ifname - << ": PDF " << version << ", " - << (fileSize + 1023) / 1024 << "kB"); + << ": PDF " << version << ", " + << (fileSize + 1023) / 1024 << "kB"); } else { @@ -964,8 +985,8 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( { //xml validation occurs when getting data OFLOG_INFO(appLogger, "file " << opt_ifname - << ": HL7 CDA file (XML Format)" << ", " - << (fileSize + 1023) / 1024 << "kB"); + << ": HL7 CDA file (XML Format)" << ", " + << (fileSize + 1023) / 1024 << "kB"); } else { @@ -977,17 +998,17 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( // - AttributeCount: 1 short (2 bytes) // Total: 50 bytes per facet const size_t facetSize32 = 3 * sizeof(Float32) - + 3 * 3 * sizeof(Float32) - + sizeof(Uint16); + + 3 * 3 * sizeof(Float32) + + sizeof(Uint16); const size_t facetSize64 = 3 * sizeof(Float64) - + 3 * 3 * sizeof(Float64) - + sizeof(Uint16); + + 3 * 3 * sizeof(Float64) + + sizeof(Uint16); // STL validation for ASCII CODE if (fileSize < 15) { // "solid " and "endsolid " markers for an ASCII file OFLOG_ERROR(appLogger, "The STL file is not long enough" - << " (" << fileSize << "kB)"); + << " (" << fileSize << "kB)"); fclose(encapfile); return EXITCODE_INVALID_INPUT_FILE; } @@ -1000,22 +1021,22 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( if (0 == strncmp("solid ", buf, 6)) { OFLOG_ERROR(appLogger, "File " << opt_ifname - << " starts with 'solid '. " - << "It is a valid STL file but it is in ASCII Code" - << "and DICOM only accepts binary STL"); + << " starts with 'solid '. " + << "It is a valid STL file but it is in ASCII Code" + << "and DICOM only accepts binary STL"); return EXITCODE_INVALID_INPUT_FILE; } - //////STL validation for Binary Format + //////STL validation for Binary Format else { OFLOG_DEBUG(appLogger, "Magic word 'solid ' not found. " - << "Validating STL file " - << "in Binary format"); + << "Validating STL file " + << "in Binary format"); // 80-byte header + 4-byte "number of triangles" for a binary file if (fileSize < 84) { OFLOG_ERROR(appLogger, "The binary STL file is not long enough" - << " (" << fileSize << "kB)"); + << " (" << fileSize << "kB)"); fclose(encapfile); return EXITCODE_INVALID_INPUT_FILE; } @@ -1025,39 +1046,39 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( for (int j = 0; j < 4; j++) ntriangleschar[j] = buf[80 + j]; ntriangleschar[4] = 0; - Uint32* nTriangles = OFreinterpret_cast(Uint32*, ntriangleschar); + Uint32 *nTriangles = OFreinterpret_cast(Uint32*, ntriangleschar); // Verify that file size equals the sum of // header + nTriangles value + all triangles OFLOG_DEBUG(appLogger, "verifying if the file size is consistent"); if (fileSize == (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize32) || - fileSize == (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize64)) + fileSize == (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize64)) { OFLOG_DEBUG(appLogger, "File " << opt_ifname - << " passed binary STL validation." << OFendl - << "Assuming valid STL file " - << "in binary format" + << " passed binary STL validation." << OFendl + << "Assuming valid STL file " + << "in binary format" ); OFLOG_TRACE(appLogger, "The binary STL file is:" << OFendl - << fileSize << " kB " << " as expected." << OFendl - << (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize32) << " kB for x86" << OFendl - << (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize64) << " kB for x64" << OFendl - << "(84 + triangles number * facet size)" << OFendl - << " number of Triangles " << *OFconst_cast(Uint32*, nTriangles) << OFendl - << " nTriangles (Uint32): " << nTriangles << OFendl - << " facetSize32: " << facetSize32 << OFendl - << " facetSize64: " << facetSize64 << OFendl + << fileSize << " kB " << " as expected." << OFendl + << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize32) << " kB for x86" << OFendl + << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize64) << " kB for x64" << OFendl + << "(84 + triangles number * facet size)" << OFendl + << " number of Triangles " << *OFconst_cast(Uint32 * , nTriangles) << OFendl + << " nTriangles (Uint32): " << nTriangles << OFendl + << " facetSize32: " << facetSize32 << OFendl + << " facetSize64: " << facetSize64 << OFendl ); } else { OFLOG_ERROR(appLogger, "The binary STL file is not consistent." << OFendl - << (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize32) << " kB for x86 and " - << (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize64) << " kB for x64 " << OFendl - << "(84 + triangles number * facet size)" << OFendl - << " number of Triangles " << *OFconst_cast(Uint32*, nTriangles) << OFendl - << " nTriangles (Uint32): " << nTriangles << OFendl - << " facetSize32: " << facetSize32 << OFendl - << " facetSize64: " << facetSize64 << OFendl + << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize32) << " kB for x86 and " + << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize64) << " kB for x64 " << OFendl + << "(84 + triangles number * facet size)" << OFendl + << " number of Triangles " << *OFconst_cast(Uint32 * , nTriangles) << OFendl + << " nTriangles (Uint32): " << nTriangles << OFendl + << " facetSize32: " << facetSize32 << OFendl + << " facetSize64: " << facetSize64 << OFendl ); fclose(encapfile); return EXITCODE_INVALID_INPUT_FILE; @@ -1067,7 +1088,7 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( else { OFLOG_WARN(appLogger, "Filetype not supported or filetype not set. Current ftype is " << ftype << OFendl - << "The name of the passed logger is: " << appLogger.getName()); + << "The name of the passed logger is: " << appLogger.getName()); } } } @@ -1082,9 +1103,18 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( if (elem) { size_t numBytes = fileSize; + // according to CP 1851 + result = dataset->putAndInsertUint32(DCM_EncapsulatedDocumentLength, OFstatic_cast(Uint32, numBytes)); if (numBytes & 1) ++numBytes; Uint8 *bytes = NULL; - result = elem->createUint8Array(OFstatic_cast(Uint32, numBytes), bytes); + if (result.good()) + { + result = elem->createUint8Array(OFstatic_cast(Uint32, numBytes), bytes); + } + else + { + return EXITCODE_CANNOT_WRITE_OUTPUT_FILE; + } if (result.good()) { // blank pad byte @@ -1096,6 +1126,10 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( return EXITCODE_CANNOT_READ_INPUT_FILE; } } + else + { + return EXITCODE_MEMORY_EXHAUSTED; + } } else { @@ -1126,8 +1160,8 @@ int DcmEncapsulatedDocument::insertEncapsulatedDocument( } OFCondition DcmEncapsulatedDocument::createHeader( - DcmItem *dataset, - OFLogger& logger) + DcmItem *dataset, + OFLogger &logger) { OFCondition result = EC_Normal; char buf[80]; @@ -1143,7 +1177,7 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (result.good()) result = dataset->insertEmptyElement(DCM_AcquisitionDateTime); if (result.good()) { - if (opt_conceptCSD!="" && opt_conceptCV != "" && opt_conceptCM != "") + if (opt_conceptCSD != "" && opt_conceptCV != "" && opt_conceptCM != "") { result = DcmCodec::insertCodeSequence(dataset, DCM_ConceptNameCodeSequence, opt_conceptCSD.c_str(), @@ -1158,7 +1192,7 @@ OFCondition DcmEncapsulatedDocument::createHeader( // insert const value attributes if (result.good()) { - result = dataset->putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 100"); + result = dataset->putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 100"); } //insert encapsulated file storage UID (CDA/PDF/STL) if (result.good()) @@ -1179,9 +1213,9 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (opt_frameOfReferenceUID.empty()) { OFLOG_DEBUG(logger, "Frame of Reference UID " - << DCM_FrameOfReferenceUID - << " value was empty, generating a new one." - ); + << DCM_FrameOfReferenceUID + << " value was empty, generating a new one." + ); dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT); opt_frameOfReferenceUID = buf; } @@ -1190,9 +1224,9 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (DcmUniqueIdentifier::checkStringValue(opt_frameOfReferenceUID, "1").bad()) { OFLOG_DEBUG(logger, "Frame of Reference UID " - << DCM_FrameOfReferenceUID - << " value was faulty, generating a new one." - ); + << DCM_FrameOfReferenceUID + << " value was faulty, generating a new one." + ); dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT); opt_frameOfReferenceUID = buf; } @@ -1202,20 +1236,21 @@ OFCondition DcmEncapsulatedDocument::createHeader( OFLOG_TRACE(logger, "Inserting Frame of Reference info to dataset"); result = dataset->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, opt_frameOfReferenceUID); } - if (result.good())result = dataset->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, opt_positionReferenceIndicator); + if (result.good()) + result = dataset->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, opt_positionReferenceIndicator); OFLOG_TRACE(logger, "Validating and inserting Enhanced General Equipment fields"); if (result.good()) { if (opt_manufacturer.empty()) { - opt_manufacturer="DCMTK_MANUFACTURING"; + opt_manufacturer = "DCMTK_MANUFACTURING"; OFLOG_WARN(logger, "No Manufacturer " - << DCM_Manufacturer - << " provided nor found in series. This attribute is " - << "required for Enhanced General Equipment module. " - << opt_manufacturer - << " will be inserted as dummy value." - ); + << DCM_Manufacturer + << " provided nor found in series. This attribute is " + << "required for Enhanced General Equipment module. " + << opt_manufacturer + << " will be inserted as dummy value." + ); } result = dataset->putAndInsertOFStringArray(DCM_Manufacturer, opt_manufacturer); } @@ -1223,14 +1258,14 @@ OFCondition DcmEncapsulatedDocument::createHeader( { if (opt_manufacturerModelName.empty()) { - opt_manufacturerModelName="DCMTK_3DMODEL_3"; + opt_manufacturerModelName = "DCMTK_3DMODEL_3"; OFLOG_WARN(logger, "No Manufacturer Model Name " - << DCM_ManufacturerModelName - << " provided nor found in series. This attribute is " - << "required for Enhanced General Equipment module. " - << opt_manufacturerModelName - << " will be inserted as dummy value." - ); + << DCM_ManufacturerModelName + << " provided nor found in series. This attribute is " + << "required for Enhanced General Equipment module. " + << opt_manufacturerModelName + << " will be inserted as dummy value." + ); } result = dataset->putAndInsertOFStringArray(DCM_ManufacturerModelName, opt_manufacturerModelName); } @@ -1238,14 +1273,14 @@ OFCondition DcmEncapsulatedDocument::createHeader( { if (opt_deviceSerialNumber.empty()) { - opt_deviceSerialNumber="DCMTK01234567890"; + opt_deviceSerialNumber = "DCMTK01234567890"; OFLOG_WARN(logger, "No Device Serial Number " - << DCM_DeviceSerialNumber - << " provided nor found in series. This attribute is " - << "required for Enhanced General Equipment module. " - << opt_deviceSerialNumber - << " will be inserted as dummy value." - ); + << DCM_DeviceSerialNumber + << " provided nor found in series. This attribute is " + << "required for Enhanced General Equipment module. " + << opt_deviceSerialNumber + << " will be inserted as dummy value." + ); } result = dataset->putAndInsertOFStringArray(DCM_DeviceSerialNumber, opt_deviceSerialNumber); } @@ -1253,14 +1288,14 @@ OFCondition DcmEncapsulatedDocument::createHeader( { if (opt_softwareVersions.empty()) { - opt_softwareVersions=OFFIS_DCMTK_VERSION; + opt_softwareVersions = OFFIS_DCMTK_VERSION; OFLOG_WARN(logger, "No Software Versions " - << DCM_SoftwareVersions - << " provided nor found in series. This attribute is " - << "required for Enhanced General Equipment module. " - << opt_softwareVersions - << " will be inserted as dummy value." - ); + << DCM_SoftwareVersions + << " provided nor found in series. This attribute is " + << "required for Enhanced General Equipment module. " + << opt_softwareVersions + << " will be inserted as dummy value." + ); } result = dataset->putAndInsertOFStringArray(DCM_SoftwareVersions, opt_softwareVersions); } @@ -1269,17 +1304,17 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (opt_measurementUnitsCSD != "" && opt_measurementUnitsCV != "" && opt_measurementUnitsCM != "") { result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence, - opt_measurementUnitsCSD.c_str(), - opt_measurementUnitsCV.c_str(), - opt_measurementUnitsCM.c_str()); + opt_measurementUnitsCSD.c_str(), + opt_measurementUnitsCV.c_str(), + opt_measurementUnitsCM.c_str()); } else { OFLOG_DEBUG(logger, "Measurement Units Code Sequence " - << DCM_FrameOfReferenceUID - << "had one or more empty values, generating default values." - ); - result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence, "UCUM","um","um"); + << DCM_FrameOfReferenceUID + << "had one or more empty values, generating default values." + ); + result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence, "UCUM", "um", "um"); } } if (result.good()) @@ -1291,7 +1326,7 @@ OFCondition DcmEncapsulatedDocument::createHeader( } if (result.good()) { - if (ftype=="stl") + if (ftype == "stl") { result = dataset->putAndInsertString(DCM_Modality, "M3D"); } @@ -1317,13 +1352,13 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (result.good()) { // according to C.24.2.1 on part 3, (0042,0012) is text/XML for CDA. - if (ftype=="cda") + if (ftype == "cda") result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "text/XML"); // according to A.45.1.4.1 on part 3, MIME Type is application/pdf for PDF. - if (ftype=="pdf") + if (ftype == "pdf") result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "application/pdf"); // according to A.85.1.4.2 on part 3, MIME Type is model/stl. - if (ftype=="stl") + if (ftype == "stl") result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "model/stl"); } // there is no way we could determine a meaningful series number, so we just use a constant. @@ -1335,11 +1370,11 @@ OFCondition DcmEncapsulatedDocument::createHeader( if (result.good()) result = dataset->putAndInsertString(DCM_PatientBirthDate, opt_patientBirthdate.c_str()); if (result.good()) result = dataset->putAndInsertString(DCM_PatientSex, opt_patientSex.c_str()); if (result.good()) result = dataset->putAndInsertString(DCM_BurnedInAnnotation, opt_annotation ? "YES" : "NO"); - if (strlen(cda_mediaTypes.c_str()) >0) + if (strlen(cda_mediaTypes.c_str()) > 0) { if (result.good()) result = dataset->putAndInsertString(DCM_ListOfMIMETypes, cda_mediaTypes.c_str()); } - if (hl7_InstanceIdentifier.size() >0) + if (hl7_InstanceIdentifier.size() > 0) { if (result.good()) result = dataset->putAndInsertString(DCM_HL7InstanceIdentifier, hl7_InstanceIdentifier.c_str()); } @@ -1371,7 +1406,10 @@ OFCondition DcmEncapsulatedDocument::applyOverrideKeys(DcmDataset *outputDset) if (cond.bad()) { OFString err; - err += "Bad override key/path: "; err += *path; err += ": "; err += cond.text(); + err += "Bad override key/path: "; + err += *path; + err += ": "; + err += cond.text(); return makeOFCondition(OFM_dcmdata, 18, OF_error, err.c_str()); } path++; @@ -1379,7 +1417,7 @@ OFCondition DcmEncapsulatedDocument::applyOverrideKeys(DcmDataset *outputDset) return cond; } -void DcmEncapsulatedDocument::setOverrideKeys(const OFList& ovkeys) +void DcmEncapsulatedDocument::setOverrideKeys(const OFList &ovkeys) { OFListConstIterator(OFString) it = ovkeys.begin(); OFListConstIterator(OFString) end = ovkeys.end(); @@ -1393,8 +1431,8 @@ void DcmEncapsulatedDocument::setOverrideKeys(const OFList& ovkeys) OFCondition DcmEncapsulatedDocument::saveFile(DcmFileFormat fileformat) { return fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, - opt_opadenc, OFstatic_cast(Uint32, opt_filepad), - OFstatic_cast(Uint32, opt_itempad)); + opt_opadenc, OFstatic_cast(Uint32, opt_filepad), + OFstatic_cast(Uint32, opt_itempad)); } OFString DcmEncapsulatedDocument::getInputFileName() @@ -1404,7 +1442,7 @@ OFString DcmEncapsulatedDocument::getInputFileName() void DcmEncapsulatedDocument::setInputFileName(OFString fName) { - opt_ifname= fName; + opt_ifname = fName; } OFString DcmEncapsulatedDocument::getOutputFileName() diff --git a/dcmdata/libsrc/dcerror.cc b/dcmdata/libsrc/dcerror.cc index be125dd7..538cf498 100644 --- a/dcmdata/libsrc/dcerror.cc +++ b/dcmdata/libsrc/dcerror.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -62,22 +62,23 @@ makeOFConditionConst(EC_SequDelimitationItemMissing, OFM_dcmdata, 34, OF_err // error code 37 is reserved for XML conversion error messages (see below) makeOFConditionConst(EC_ItemDelimitationItemMissing, OFM_dcmdata, 38, OF_error, "Item Delimitation Item missing" ); makeOFConditionConst(EC_PrematureSequDelimitationItem, OFM_dcmdata, 39, OF_error, "Sequence Delimitation Item occurred before Item was completely read" ); -makeOFConditionConst(EC_InvalidDICOMDIR, OFM_dcmdata, 40, OF_error, "Invalid DICOMDIR" ); +makeOFConditionConst(EC_InvalidDICOMDIR, OFM_dcmdata, 40, OF_error, "Invalid DICOMDIR" ); makeOFConditionConst(EC_UnknownVR, OFM_dcmdata, 41, OF_error, "Unknown VR: Tag not found in data dictionary" ); -makeOFConditionConst(EC_InvalidValue, OFM_dcmdata, 42, OF_error, "Invalid Value"); -makeOFConditionConst(EC_ItemNotFound, OFM_dcmdata, 43, OF_error, "Item not found"); -makeOFConditionConst(EC_UnknownTransferSyntax, OFM_dcmdata, 44, OF_error, "Unknown Transfer Syntax"); -makeOFConditionConst(EC_CannotCheck, OFM_dcmdata, 45, OF_error, "Cannot perform check"); -makeOFConditionConst(EC_MissingValue, OFM_dcmdata, 46, OF_error, "Missing value"); -makeOFConditionConst(EC_MissingAttribute, OFM_dcmdata, 47, OF_error, "Missing attribute"); -makeOFConditionConst(EC_InternalError, OFM_dcmdata, 48, OF_error, "Internal error"); -makeOFConditionConst(EC_InvalidCharacter, OFM_dcmdata, 49, OF_error, "Invalid character"); +makeOFConditionConst(EC_InvalidValue, OFM_dcmdata, 42, OF_error, "Invalid Value" ); +makeOFConditionConst(EC_ItemNotFound, OFM_dcmdata, 43, OF_error, "Item not found" ); +makeOFConditionConst(EC_UnknownTransferSyntax, OFM_dcmdata, 44, OF_error, "Unknown Transfer Syntax" ); +makeOFConditionConst(EC_CannotCheck, OFM_dcmdata, 45, OF_error, "Cannot perform check" ); +makeOFConditionConst(EC_MissingValue, OFM_dcmdata, 46, OF_error, "Missing value" ); +makeOFConditionConst(EC_MissingAttribute, OFM_dcmdata, 47, OF_error, "Missing attribute" ); +makeOFConditionConst(EC_InternalError, OFM_dcmdata, 48, OF_error, "Internal error" ); +makeOFConditionConst(EC_InvalidCharacter, OFM_dcmdata, 49, OF_error, "Invalid character" ); // error code 50 is reserved for determine start fragment error messages (see below) -makeOFConditionConst(EC_UndefinedLengthOBOW, OFM_dcmdata, 51, OF_error, "Illegal element with OB or OW Value Representation and undefined length encountered"); -makeOFConditionConst(EC_VOI_LUT_OBOW, OFM_dcmdata, 52, OF_error, "Illegal VOI LUT Sequence element with OB or OW Value Representation and explicit length encountered"); -makeOFConditionConst(EC_PixelDataExplLengthIllegal, OFM_dcmdata, 53, OF_error, "Pixel data in top level dataset in compressed Transfer Syntax uses explicit length"); +makeOFConditionConst(EC_UndefinedLengthOBOW, OFM_dcmdata, 51, OF_error, "Illegal element with OB or OW Value Representation and undefined length encountered" ); +makeOFConditionConst(EC_VOI_LUT_OBOW, OFM_dcmdata, 52, OF_error, "Illegal VOI LUT Sequence element with OB or OW Value Representation and explicit length encountered" ); +makeOFConditionConst(EC_PixelDataExplLengthIllegal, OFM_dcmdata, 53, OF_error, "Pixel data in top level dataset in compressed Transfer Syntax uses explicit length" ); makeOFConditionConst(EC_ElemLengthExceeds32BitField, OFM_dcmdata, 54, OF_error, "Length of element value exceeds maximum of 32-bit length field" ); - +makeOFConditionConst(EC_CannotWriteJsonNumber, OFM_dcmdata, 55, OF_error, "Cannot write 'nan' or 'inf' as JSON number" ); +makeOFConditionConst(EC_CannotWriteJsonInlineBinary, OFM_dcmdata, 56, OF_error, "JSON InlineBinary encoding not supported for compressed pixel data" ); const unsigned short EC_CODE_CannotSelectCharacterSet = 35; const unsigned short EC_CODE_CannotConvertCharacterSet = 36; diff --git a/dcmdata/libsrc/dcfilefo.cc b/dcmdata/libsrc/dcfilefo.cc index 452ff97e..4b6b6489 100644 --- a/dcmdata/libsrc/dcfilefo.cc +++ b/dcmdata/libsrc/dcfilefo.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -39,6 +39,7 @@ #include "dcmtk/dcmdata/dcvrus.h" #include "dcmtk/dcmdata/dcvrae.h" #include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrur.h" #include "dcmtk/dcmdata/dcmetinf.h" #include "dcmtk/dcmdata/dcdeftag.h" @@ -231,46 +232,38 @@ OFCondition DcmFileFormat::writeXML(STD_NAMESPACE ostream &out, OFCondition DcmFileFormat::writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format) { - if (format.printMetaheaderInformation) + OFBool meta = format.printMetaheaderInformation; + DcmDataset *dset = getDataset(); + OFCondition status = EC_Normal; + if (meta) { - if (!itemList->empty()) + // print out meta-header elements and dataset (non-standard) + DcmMetaInfo *metinf = getMetaInfo(); + out << format.indent() << "{" << format.newline(); + if (metinf) { - out << format.indent() << "{" << format.newline(); - // write content of all children (DcmObject) - itemList->seek(ELP_first); - OFCondition status = EC_Normal; - status = itemList->get()->writeJson(out, format); - while (status.good() && itemList->seek(ELP_next)) - { - out << "," << format.newline(); - status = itemList->get()->writeJson(out, format); - } - out << format.newline() << format.indent() << "}" << format.newline(); - return status; + status = metinf->writeJsonExt(out, format, OFFalse, OFFalse); + out << format.newline(); } - else + if (dset && status.good()) { - return EC_CorruptedData; + status = dset->writeJsonExt(out, format, OFFalse, OFFalse); } + out << format.newline() << format.indent() << "}" << format.newline(); } else { - if (DcmDataset *dset = getDataset()) + // standard case: only print dataset + if (dset) { - out << format.indent() << "{" << format.newline(); - OFCondition status = EC_Normal; - // write content of dataset - status = dset->writeJson(out, format); - out << format.newline() << format.indent() << "}" << format.newline(); - return status; + status = dset->writeJsonExt(out, format, OFTrue, OFTrue); } else { out << format.indent() << "{}" << format.newline(); - return EC_Normal; } } - return EC_Normal; + return status; } @@ -509,6 +502,17 @@ OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo, } DCMDATA_WARN("DcmFileFormat: Don't know how to handle " << tag.getTagName()); } + else if ((xtag == DCM_SourcePresentationAddress) || // (0002,0026) + (xtag == DCM_SendingPresentationAddress) || // (0002,0027) + (xtag == DCM_ReceivingPresentationAddress)) // (0002,0028) + { + if (elem == NULL) + { + elem = new DcmUniversalResourceIdentifierOrLocator(tag); + metainfo->insert(elem, OFTrue); + } + DCMDATA_WARN("DcmFileFormat: Don't know how to handle " << tag.getTagName()); + } else if (xtag == DCM_PrivateInformationCreatorUID) // (0002,0100) { if (elem == NULL) diff --git a/dcmdata/libsrc/dcitem.cc b/dcmdata/libsrc/dcitem.cc index 1a62caf9..045f3c93 100644 --- a/dcmdata/libsrc/dcitem.cc +++ b/dcmdata/libsrc/dcitem.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -554,32 +554,74 @@ OFCondition DcmItem::writeXML(STD_NAMESPACE ostream &out, // ******************************** - OFCondition DcmItem::writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format) { + return writeJsonExt(out, format, OFTrue, OFFalse); +} + +// ******************************** + +OFCondition DcmItem::writeJsonExt(STD_NAMESPACE ostream &out, + DcmJsonFormat &format, + OFBool printBraces, + OFBool printNewline) +{ + size_t num_printed = 0; + OFBool first = OFTrue; + DcmObject *elem = NULL; + OFCondition status = EC_Normal; + if (!elementList->empty()) { - // write content of all children - out << "{" << format.newline(); + // iterate through all elements in this item elementList->seek(ELP_first); - OFCondition status = EC_Normal; - status = elementList->get()->writeJson(out, format); - while (status.good() && elementList->seek(ELP_next)) + do { - out << "," << format.newline(); - status = elementList->get()->writeJson(out, format); + // get next item + elem = elementList->get(); + + // check if this is a group length, and if so, ignore + if (elem->getTag().getElement() != 0) + { + // if this is the first element to be printed, print opening braces if needed + if (first && printBraces) out << "{" << format.newline(); + + // if this is not the first element to be printed, start with a comma + if (!first) out << "," << format.newline(); + + // print element + status = elem->writeJson(out, format); + first = OFFalse; + num_printed++; + } + } + while (status.good() && elementList->seek(ELP_next)); + + // print closing braces if and only if there were opening braces + if (num_printed > 0 && printBraces) + { + out << format.newline() << format.indent() << "}"; + if (printNewline) out << format.newline(); } - out << format.newline() << format.indent() << "}"; - return status; } - else + + // if no element was printed (item empty or only group list elements) + if (num_printed == 0) { - out << "{}" << format.newline(); + if (printBraces) + { + // print empty braces if requested + out << "{}"; + if (printNewline) out << format.newline(); + } } - return EC_Normal; + + return status; + } + // ******************************** @@ -1610,7 +1652,7 @@ OFCondition DcmItem::writeSignatureFormat(DcmOutputStream &outStream, do { dO = elementList->get(); - if (dO->transferState() != ERW_ready) + if (dO->isSignable() && dO->transferState() != ERW_ready) errorFlag = dO->writeSignatureFormat(outStream, oxfer, enctype, wcache); } while (errorFlag.good() && elementList->seek(ELP_next)); } @@ -3447,6 +3489,11 @@ OFCondition DcmItem::putAndInsertUint8Array(const DcmTag& tag, } else elem = new DcmPolymorphOBOW(tag); break; + case EVR_px: + elem = new DcmPixelData(tag); + if (elem != NULL) + elem->setVR(EVR_OB); + break; case EVR_UNKNOWN: /* Unknown VR, e.g. tag not found in data dictionary */ status = EC_UnknownVR; @@ -3538,11 +3585,16 @@ OFCondition DcmItem::putAndInsertUint16Array(const DcmTag& tag, if (tag == DCM_PixelData) { elem = new DcmPixelData(tag); - if (elem != NULL) elem->setVR(EVR_OW); - } - else + if (elem != NULL) + elem->setVR(EVR_OW); + } else elem = new DcmPolymorphOBOW(tag); break; + case EVR_px: + elem = new DcmPixelData(tag); + if (elem != NULL) + elem->setVR(EVR_OW); + break; case EVR_xs: /* special handling */ elem = new DcmUnsignedShort(DcmTag(tag, EVR_US)); @@ -3858,6 +3910,9 @@ OFCondition DcmItem::putAndInsertFloat64(const DcmTag& tag, DcmElement *elem = NULL; switch(tag.getEVR()) { + case EVR_DS: + elem = new DcmDecimalString(tag); + break; case EVR_FD: elem = new DcmFloatingPointDouble(tag); break; @@ -4152,7 +4207,7 @@ OFCondition DcmItem::insertSequenceItem(const DcmTag &seqTag, if (itemNum == -1) { /* insert given item before last entry */ - status = sequence->insert(item, count - 1, OFTrue /*before*/); + status = sequence->insert(item, DCM_EndOfListIndex, OFTrue /*before*/); } else { /* insert given item before specified entry */ status = sequence->insert(item, OFstatic_cast(unsigned long, itemNum), OFTrue /*before*/); @@ -4441,6 +4496,8 @@ OFCondition DcmItem::newDicomElement(DcmElement *&newElement, */ if (newTag.getEVR() != EVR_UNKNOWN) { + DCMDATA_DEBUG("DcmItem::newDicomElement() reverted VR of element " << tag + << " from 'UN' to '" << newTag.getVRName() << "'"); tag.setVR(newTag.getVR()); evr = tag.getEVR(); readAsUN = OFTrue; @@ -4557,7 +4614,7 @@ OFCondition DcmItem::newDicomElement(DcmElement *&newElement, // sequences and items: case EVR_SQ : - newElement = new DcmSequenceOfItems(tag, length); + newElement = new DcmSequenceOfItems(tag, length, readAsUN); break; case EVR_na : if (tag.getXTag() == DCM_Item) @@ -4587,6 +4644,10 @@ OFCondition DcmItem::newDicomElement(DcmElement *&newElement, newElement = new DcmOtherByteOtherWord(tag, length); break; + case EVR_px : + newElement = new DcmPixelData(tag, length); + break; + // This case should only occur if we encounter an element with an invalid // "Pi" VR. Make sure this does not cause problems later on case EVR_PixelData : @@ -4639,7 +4700,21 @@ OFCondition DcmItem::newDicomElement(DcmElement *&newElement, } } } - else + else if (tag.isPrivate()) + { + // look up VR in private data dictionary + DcmTag newTag(tag.getXTag(), tag.getPrivateCreator()); + // special handling for private pixel data (compressed or uncompressed) + if (newTag.getEVR() == EVR_px) + { + DCMDATA_WARN("Found private element " << tag << " with VR " << tag.getVRName() + << " and undefined length, reading a pixel sequence according to data dictionary"); + newElement = new DcmPixelData(tag, length); + } + } + // no element has been created yet and no error reported + if ((newElement == NULL) && l_error.good()) + { if (length == DCM_UndefinedLength) { // The attribute is OB or OW but is encoded with undefined @@ -4658,17 +4733,17 @@ OFCondition DcmItem::newDicomElement(DcmElement *&newElement, OFCondition tempcond = EC_UndefinedLengthOBOW; DCMDATA_WARN("DcmItem: Parse error in " << tag << ": " << tempcond.text()); newElement = new DcmSequenceOfItems(tag, length); - } - else - { + } else { // bail out with an error l_error = EC_UndefinedLengthOBOW; DCMDATA_ERROR("DcmItem: Parse error in " << tag << ": " << l_error.text()); } } } else { + // default case newElement = new DcmOtherByteOtherWord(tag, length); } + } break; // read unknown types as byte string: diff --git a/dcmdata/libsrc/dcjson.cc b/dcmdata/libsrc/dcjson.cc index 9efb1b9b..2b202640 100644 --- a/dcmdata/libsrc/dcjson.cc +++ b/dcmdata/libsrc/dcjson.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2017, OFFIS e.V. + * Copyright (C) 2016-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -78,15 +78,21 @@ void DcmJsonFormat::escapeControlCharacters(STD_NAMESPACE ostream &out, const OF // Formats the number to JSON standard as DecimalString void DcmJsonFormat::normalizeDecimalString(OFString &value) { + // remove all plus characters that may occur in the string. + // These are permitted in DICOM but not in Json. + size_t pos; + while (OFString_npos != (pos = value.find('+'))) + value.erase(pos,1); + OFBool minus = OFFalse; - if (value[0] == '-') + if (value.length() > 0 && value[0] == '-') { value = value.substr(1); minus = OFTrue; } - size_t pos = value.find_first_not_of("0"); + pos = value.find_first_not_of("0"); if (pos == OFString_npos) value = "0"; @@ -105,15 +111,21 @@ void DcmJsonFormat::normalizeDecimalString(OFString &value) // Formats the number to JSON standard as IntegerString void DcmJsonFormat::normalizeIntegerString(OFString &value) { + // remove all plus characters that may occur in the string. + // These are permitted in DICOM but not in Json. + size_t pos; + while (OFString_npos != (pos = value.find('+'))) + value.erase(pos,1); + OFBool minus = OFFalse; - if (value[0] == '-') + if (value.length() > 0 && value[0] == '-') { value = value.substr(1); minus = OFTrue; } - size_t pos = value.find_first_not_of("0"); + pos = value.find_first_not_of("0"); if (pos == OFString_npos) value = "0"; @@ -215,7 +227,7 @@ void DcmJsonFormat::printNextArrayElementPrefix(STD_NAMESPACE ostream &out) // This also manipulate uri String, if BulkDataURI should be printed. OFBool DcmJsonFormat::asBulkDataURI(const DcmTagKey& /*tag*/, OFString& /*uri*/) { - return false; + return OFFalse; } //Class for formatted output diff --git a/dcmdata/libsrc/dclist.cc b/dcmdata/libsrc/dclist.cc index d859672d..3104da27 100644 --- a/dcmdata/libsrc/dclist.cc +++ b/dcmdata/libsrc/dclist.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2010, OFFIS e.V. + * Copyright (C) 1994-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -71,7 +71,7 @@ DcmList::~DcmList() do { DcmListNode *temp = firstNode; firstNode = firstNode->nextNode; - // delete temp->objNodeValue;; // dangerous! + // delete temp->objNodeValue; // dangerous! delete temp; } while ( firstNode != NULL ); currentNode = firstNode = lastNode = NULL; @@ -254,10 +254,23 @@ DcmObject *DcmList::seek( E_ListPos pos ) DcmObject *DcmList::seek_to(unsigned long absolute_position) { - const unsigned long tmppos = absolute_position < cardinality ? absolute_position : cardinality; - seek( ELP_first ); - for (unsigned long i = 0; i < tmppos; i++) - seek( ELP_next ); + if (absolute_position < cardinality / 2) + { + /* iterate over first half of the list */ + seek( ELP_first ); + for (unsigned long i = 0; i < absolute_position; i++) + seek( ELP_next ); + } + else if (absolute_position < cardinality) + { + /* iterate over second half of the list (starting from the end) */ + seek( ELP_last ); + for (unsigned long i = absolute_position + 1; i < cardinality; i++) + seek( ELP_prev ); + } else { + /* invalid position */ + currentNode = NULL; + } return get( ELP_atpos ); } diff --git a/dcmdata/libsrc/dcmetinf.cc b/dcmdata/libsrc/dcmetinf.cc index 68b68784..8bef02b5 100644 --- a/dcmdata/libsrc/dcmetinf.cc +++ b/dcmdata/libsrc/dcmetinf.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -380,8 +380,12 @@ OFCondition DcmMetaInfo::readGroupLength(DcmInputStream &inStream, l_error = (OFstatic_cast(DcmUnsignedLong *, elementList->get()))->getUint32(headerLen); DCMDATA_TRACE("DcmMetaInfo::readGroupLength() Group Length of File Meta Header = " << headerLen + bytesRead); } else { - l_error = EC_CorruptedData; DCMDATA_WARN("DcmMetaInfo: No Group Length available in Meta Information Header"); + /* missing group length could be ignored (if no other error occurred) */ + if (l_error == EC_StreamNotifyClient) + l_error = EC_InvalidStream; + else if (l_error != EC_InvalidStream) + l_error = EC_CorruptedData; } } } diff --git a/dcmdata/libsrc/dcobject.cc b/dcmdata/libsrc/dcobject.cc index 8d1d2ad4..13f4baeb 100644 --- a/dcmdata/libsrc/dcobject.cc +++ b/dcmdata/libsrc/dcobject.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -464,18 +464,18 @@ Uint32 DcmObject::getTagAndLengthSize(const E_TransferSyntax oxfer) const if (oxferSyn.isExplicitVR()) { - /* map "UN" to "OB" if generation of "UN" is disabled */ - DcmVR outvr(getTag().getVR().getValidEVR()); - - if (Length > 0xffff || outvr.usesExtendedLengthEncoding()) - { - // we are either using extended length encoding or the - // element length is > 64k (i.e. we have to convert to OB/UN). - // In any case we need a 12-byte header field. - // This is also the case for any object with undefined length, - // so we don't need to check that as a special case. - return 12; - } + /* map "UN" to "OB" if generation of "UN" is disabled */ + DcmVR outvr(getTag().getVR().getValidEVR()); + + if (Length > 0xffff || outvr.usesExtendedLengthEncoding()) + { + /* We are either using extended length encoding or the */ + /* element length is > 64k (i.e. we have to convert to OB/UN). */ + /* In any case we need a 12-byte header field. */ + /* This is also the case for any object with undefined length, */ + /* so we don't need to check that as a special case. */ + return 12; + } } return 8; } @@ -535,10 +535,13 @@ OFCondition DcmObject::writeTagAndLength(DcmOutputStream &outStream, if (Length > 0xffff && (!myvr.usesExtendedLengthEncoding())) { - // Attribute length is larger than 64 kBytes. - // We need to encode this as UN (or OB, if generation of UN is disabled - if (dcmEnableUnknownVRGeneration.get()) vr = EVR_UN; else vr = EVR_OB; - myvr.setVR(vr); + /* Attribute length is larger than 64 kBytes. */ + /* We need to encode this as UN (or OB, if generation of UN is disabled */ + if (dcmEnableUnknownVRGeneration.get()) vr = EVR_UN; else vr = EVR_OB; + myvr.setVR(vr); + /* output debug information to the logger */ + DCMDATA_DEBUG("DcmObject::writeTagAndLength() Length of element " << Tag + << " exceeds maximum of 16-bit length field, changing VR to " << myvr.getVRName()); } /* get name of data type */ diff --git a/dcmdata/libsrc/dcpath.cc b/dcmdata/libsrc/dcpath.cc index ae8acfc7..6d97682e 100644 --- a/dcmdata/libsrc/dcpath.cc +++ b/dcmdata/libsrc/dcpath.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2008-2018, OFFIS e.V. + * Copyright (C) 2008-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -20,7 +20,7 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcpath.h" #include "dcmtk/dcmdata/dcsequen.h" @@ -28,921 +28,930 @@ #define INCLUDE_CINTTYPES #include "dcmtk/ofstd/ofstdinc.h" - /*******************************************************************/ /* Implementation of class DcmPath */ /*******************************************************************/ // Constructor -DcmPath::DcmPath() : - m_path() +DcmPath::DcmPath() + : m_path() { } - // Construct from existing path (kind of copy constructor) -DcmPath::DcmPath(const OFList& currentPath) : - m_path() +DcmPath::DcmPath(const OFList& currentPath) + : m_path() { - OFListConstIterator(DcmPathNode*) it = currentPath.begin(); - OFListConstIterator(DcmPathNode*) endOfPath = currentPath.end(); - while (it != endOfPath) - { - m_path.push_back(new DcmPathNode( (*it)->m_obj, (*it)->m_itemNo )); - it++; - } + OFListConstIterator(DcmPathNode*) it = currentPath.begin(); + OFListConstIterator(DcmPathNode*) endOfPath = currentPath.end(); + while (it != endOfPath) + { + m_path.push_back(new DcmPathNode((*it)->m_obj, (*it)->m_itemNo)); + it++; + } } - // Append a node to the path void DcmPath::append(DcmPathNode* node) { - if (node != NULL) - m_path.push_back(node); // do any validity checking? + if (node != NULL) + m_path.push_back(node); // do any validity checking? } - // Deletes last node from the path and frees corresponding memory void DcmPath::deleteBackNode() { - DcmPathNode* node = m_path.back(); - m_path.pop_back(); - if (node) - { - delete node; node = NULL; - } + DcmPathNode* node = m_path.back(); + m_path.pop_back(); + if (node) + { + delete node; + node = NULL; + } } - // Returns iterator to first element of the path OFListIterator(DcmPathNode*) DcmPath::begin() { - return m_path.begin(); + return m_path.begin(); } - // Returns iterator to last element of the path DcmPathNode* DcmPath::back() { - return m_path.back(); + return m_path.back(); } // Returns iterator to the end of path, i.e. dummy after actual last element OFListIterator(DcmPathNode*) DcmPath::end() { - return m_path.end(); + return m_path.end(); } - // Returns number of path nodes in the path Uint32 DcmPath::size() const { - return OFstatic_cast(Uint32, m_path.size()); + return OFstatic_cast(Uint32, m_path.size()); } - // Returns true if path is empty, i.e. number of path nodes is zero OFBool DcmPath::empty() const { - return (m_path.size() == 0); + return (m_path.size() == 0); } - // Returns string representation of the path OFString DcmPath::toString() const { - OFListConstIterator(DcmPathNode*) it = m_path.begin(); - OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); - OFString pathStr; DcmEVR vr; DcmObject* obj; - char buf[500]; - while (it != endOfList) - { - if ( ((*it) == NULL) || ((*it)->m_obj == NULL) ) - return "Invalid search result"; - obj = (*it)->m_obj; - vr = obj->ident(); - if ((vr == EVR_SQ) || ( obj->isLeaf()) ) - { - pathStr.append( OFconst_cast(DcmTag*, &obj->getTag())->getTagName() ); - it++; - } - else if ( (vr == EVR_item) || (vr == EVR_dataset) ) + OFListConstIterator(DcmPathNode*) it = m_path.begin(); + OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); + OFString pathStr; + DcmEVR vr; + DcmObject* obj; + char buf[500]; + while (it != endOfList) { + if (((*it) == NULL) || ((*it)->m_obj == NULL)) + return "Invalid search result"; + obj = (*it)->m_obj; + vr = obj->ident(); + if ((vr == EVR_SQ) || (obj->isLeaf())) + { + pathStr.append(OFconst_cast(DcmTag*, &obj->getTag())->getTagName()); + it++; + } + else if ((vr == EVR_item) || (vr == EVR_dataset)) + { #ifdef PRIu32 - sprintf(buf, "[%" PRIu32 "]", (*it)->m_itemNo); + sprintf(buf, "[%" PRIu32 "]", (*it)->m_itemNo); #elif SIZEOF_LONG == 8 - sprintf(buf, "[%u]", (*it)->m_itemNo); + sprintf(buf, "[%u]", (*it)->m_itemNo); #else - sprintf(buf, "[%lu]", (*it)->m_itemNo); + sprintf(buf, "[%lu]", (*it)->m_itemNo); #endif - pathStr.append(buf); - it++; - if (it != endOfList) pathStr.append("."); - } - else - { - pathStr.append(""); - it++; + pathStr.append(buf); + it++; + if (it != endOfList) + pathStr.append("."); + } + else + { + pathStr.append(""); + it++; + } } - } - return pathStr; + return pathStr; } - // Checks whether a specific group number is used in the path's path nodes OFBool DcmPath::containsGroup(const Uint16 groupNo) const { - OFListConstIterator(DcmPathNode*) it = m_path.begin(); - OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); - while (it != endOfList) - { - DcmPathNode* node = *it; - if ( (node == NULL) || (node->m_obj == NULL) ) return OFFalse; - if (node->m_obj->getGTag() == groupNo) return OFTrue; - it++; - } - return OFFalse; + OFListConstIterator(DcmPathNode*) it = m_path.begin(); + OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); + while (it != endOfList) + { + DcmPathNode* node = *it; + if ((node == NULL) || (node->m_obj == NULL)) + return OFFalse; + if (node->m_obj->getGTag() == groupNo) + return OFTrue; + it++; + } + return OFFalse; } - // Helper function for findOrCreatePath(). Parses item no from start of string -OFCondition DcmPath::parseItemNoFromPath(OFString& path, // inout - Uint32& itemNo, // out - OFBool& wasWildcard) // out +OFCondition DcmPath::parseItemNoFromPath(OFString& path, // inout + Uint32& itemNo, // out + OFBool& wasWildcard) // out { - wasWildcard = OFFalse; - itemNo = 0; - // check whether there is an item to parse - size_t closePos = path.find_first_of(']', 0); - if ( (closePos != OFString_npos) && (path[0] == '[') ) - { - long int parsedNo; - // try parsing item number; parsing for %lu would cause overflows in case of negative numbers - int parsed = sscanf(path.c_str(), "[%ld]", &parsedNo); - if (parsed == 1) - { - if (parsedNo < 0) - { - OFString errMsg = "Negative item number (not permitted) at beginning of path: "; errMsg += path; - return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); - } - itemNo = OFstatic_cast(Uint32, parsedNo); - if (closePos + 1 < path.length()) // if end of path not reached, cut off "." - closePos ++; - path.erase(0, closePos + 1); // remove item from path - return EC_Normal; - } - char aChar; - parsed = sscanf(path.c_str(), "[%c]", &aChar); - if ( (parsed == 1) && (aChar =='*') ) - { - wasWildcard = OFTrue; - if (closePos + 1 < path.length()) // if end of path not reached, cut off "." - closePos ++; - path.erase(0, closePos + 1); // remove item from path - return EC_Normal; - } - } - OFString errMsg = "Unable to parse item number at beginning of path: "; errMsg += path; - return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + wasWildcard = OFFalse; + itemNo = 0; + // check whether there is an item to parse + size_t closePos = path.find_first_of(']', 0); + if ((closePos != OFString_npos) && (path[0] == '[')) + { + long int parsedNo; + // try parsing item number; parsing for %lu would cause overflows in case of negative numbers + int parsed = sscanf(path.c_str(), "[%ld]", &parsedNo); + if (parsed == 1) + { + if (parsedNo < 0) + { + OFString errMsg = "Negative item number (not permitted) at beginning of path: "; + errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + itemNo = OFstatic_cast(Uint32, parsedNo); + if (closePos + 1 < path.length()) // if end of path not reached, cut off "." + closePos++; + path.erase(0, closePos + 1); // remove item from path + return EC_Normal; + } + char aChar; + parsed = sscanf(path.c_str(), "[%c]", &aChar); + if ((parsed == 1) && (aChar == '*')) + { + wasWildcard = OFTrue; + if (closePos + 1 < path.length()) // if end of path not reached, cut off "." + closePos++; + path.erase(0, closePos + 1); // remove item from path + return EC_Normal; + } + } + OFString errMsg = "Unable to parse item number at beginning of path: "; + errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); } - // Function that parses a tag from the beginning of a path string. -OFCondition DcmPath::parseTagFromPath(OFString& path, // inout - DcmTag& tag) // out +OFCondition DcmPath::parseTagFromPath(OFString& path, // inout + DcmTag& tag) // out { - OFCondition result; - size_t pos = OFString_npos; + OFCondition result; + size_t pos = OFString_npos; - // In case we have a tag "(gggg,xxxx)" - if ( path[0] == '(') - { - pos = path.find_first_of(')', 0); - if (pos != OFString_npos) - result = DcmTag::findTagFromName(path.substr(1, pos - 1).c_str() /* "gggg,eeee" */, tag); + // In case we have a tag "(gggg,xxxx)" + if (path[0] == '(') + { + pos = path.find_first_of(')', 0); + if (pos != OFString_npos) + result = DcmTag::findTagFromName(path.substr(1, pos - 1).c_str() /* "gggg,eeee" */, tag); + else + { + OFString errMsg("Unable to parse tag at beginning of path: "); + errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + pos++; // also cut off closing bracket + } + // otherwise we could have a dictionary name else { - OFString errMsg("Unable to parse tag at beginning of path: "); errMsg += path; - return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); - } - pos++; // also cut off closing bracket - } - // otherwise we could have a dictionary name - else - { - // maybe an item follows - pos = path.find_first_of('[', 0); - if (pos == OFString_npos) - result = DcmTag::findTagFromName(path.c_str(), tag); // check full path + // maybe an item follows + pos = path.find_first_of('[', 0); + if (pos == OFString_npos) + result = DcmTag::findTagFromName(path.c_str(), tag); // check full path + else + result = DcmTag::findTagFromName(path.substr(0, pos).c_str(), tag); // parse path up to "[" char + } + // construct error message if necessary and return + if (result.bad()) + { + OFString errMsg("Unable to parse tag/dictionary name at beginning of path: "); + errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + // else remove parsed tag from path and return success else - result = DcmTag::findTagFromName(path.substr(0, pos).c_str(), tag); // parse path up to "[" char - } - // construct error message if necessary and return - if (result.bad()) - { - OFString errMsg("Unable to parse tag/dictionary name at beginning of path: "); errMsg += path; - return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); - } - // else remove parsed tag from path and return success - else - path.erase(0, pos); - return EC_Normal; -} + { + path.erase(0, pos); + } + return EC_Normal; +} // Destructor, frees memory of path nodes (but not of underlying DICOM objects) DcmPath::~DcmPath() { - // free dynamically allocated memory - while (m_path.size() != 0) - { - DcmPathNode* node = m_path.front(); - delete node; node = NULL; - m_path.pop_front(); - } + // free dynamically allocated memory + while (m_path.size() != 0) + { + DcmPathNode* node = m_path.front(); + delete node; + node = NULL; + m_path.pop_front(); + } } - // Separate a string path into the different nodes -OFCondition DcmPath::separatePathNodes(const OFString& path, - OFList& result) +OFCondition DcmPath::separatePathNodes(const OFString& path, OFList& result) { - OFString pathStr(path); - OFCondition status = EC_Normal; - OFBool nextIsItem = OFTrue; - Uint32 itemNo = 0; - OFBool isWildcard = OFFalse; - - // initialize parsing loop - if (!pathStr.empty()) - { - if (pathStr[0] != '[') - nextIsItem = OFFalse; - } - - char buf[100]; - // parse node for node and only stop if error occurs or parsing completes - while ( !pathStr.empty() ) - { - if (nextIsItem) - { - status = parseItemNoFromPath(pathStr, itemNo, isWildcard); - if (status.bad()) return status; - if (isWildcard) - result.push_back("[*]"); - else - { + OFString pathStr(path); + OFCondition status = EC_Normal; + OFBool nextIsItem = OFTrue; + Uint32 itemNo = 0; + OFBool isWildcard = OFFalse; + + // initialize parsing loop + if (!pathStr.empty()) + { + if (pathStr[0] != '[') + nextIsItem = OFFalse; + } + + char buf[100]; + // parse node for node and only stop if error occurs or parsing completes + while (!pathStr.empty()) + { + if (nextIsItem) + { + status = parseItemNoFromPath(pathStr, itemNo, isWildcard); + if (status.bad()) + return status; + if (isWildcard) + result.push_back("[*]"); + else + { #ifdef PRIu32 - if (sprintf(buf, "[%" PRIu32 "]", itemNo) < 2) return EC_IllegalParameter; + if (sprintf(buf, "[%" PRIu32 "]", itemNo) < 2) + return EC_IllegalParameter; #elif SIZEOF_LONG == 8 - if (sprintf(buf, "[%u]", itemNo) < 2) return EC_IllegalParameter; + if (sprintf(buf, "[%u]", itemNo) < 2) + return EC_IllegalParameter; #else - if (sprintf(buf, "[%lu]", itemNo) < 2) return EC_IllegalParameter; + if (sprintf(buf, "[%lu]", itemNo) < 2) + return EC_IllegalParameter; #endif - result.push_back(buf); - } - nextIsItem = OFFalse; - } - else - { - DcmTag tag; - status = parseTagFromPath(pathStr, tag); - if (status.bad()) - return status; - if (sprintf(buf, "(%04X,%04X)", tag.getGroup(), tag.getElement()) != 11) - return EC_IllegalParameter; - result.push_back(buf); - nextIsItem = OFTrue; + result.push_back(buf); + } + nextIsItem = OFFalse; + } + else + { + DcmTag tag; + status = parseTagFromPath(pathStr, tag); + if (status.bad()) + return status; + if (sprintf(buf, "(%04X,%04X)", tag.getGroup(), tag.getElement()) != 11) + return EC_IllegalParameter; + result.push_back(buf); + nextIsItem = OFTrue; + } } - } - return status; + return status; } - /*******************************************************************/ /* Implementation of class DcmPathProcessor */ /*******************************************************************/ - // Constructor, constructs an empty path processor -DcmPathProcessor::DcmPathProcessor() : - m_currentPath(), - m_results(), - m_createIfNecessary(OFFalse), - m_checkPrivateReservations(OFTrue), - m_itemWildcardsEnabled(OFTrue) +DcmPathProcessor::DcmPathProcessor() + : m_currentPath() + , m_results() + , m_createIfNecessary(OFFalse) + , m_checkPrivateReservations(OFTrue) + , m_itemWildcardsEnabled(OFTrue) { } - // enables (class default:enabled) or disables checking of private reservations void DcmPathProcessor::checkPrivateReservations(const OFBool doChecking) { - m_checkPrivateReservations = doChecking; + m_checkPrivateReservations = doChecking; } - // enables (class default:enabled) or disables support for item wildcards void DcmPathProcessor::setItemWildcardSupport(const OFBool supported) { - m_itemWildcardsEnabled = supported; + m_itemWildcardsEnabled = supported; } - // Permits finding and creating DICOM object hierarchies based on a path string -OFCondition DcmPathProcessor::findOrCreatePath(DcmObject* obj, - const OFString& path, - OFBool createIfNecessary) +OFCondition DcmPathProcessor::findOrCreatePath(DcmObject* obj, const OFString& path, OFBool createIfNecessary) { - // check input parameters - if ( (obj == NULL) || path.empty()) - return EC_IllegalParameter; - - if (!m_itemWildcardsEnabled) - { - if (path.find('*') != OFString_npos) - { - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); - } - } - clear(); - m_createIfNecessary = createIfNecessary; - - // do real work in private member functions - OFString pathCopy = path; - if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) - return findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); - else if (obj->ident() == EVR_SQ) - return findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); - else - return EC_IllegalParameter; -} + // check input parameters + if ((obj == NULL) || path.empty()) + return EC_IllegalParameter; + if (!m_itemWildcardsEnabled) + { + if (path.find('*') != OFString_npos) + { + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); + } + } + clear(); + m_createIfNecessary = createIfNecessary; + + // do real work in private member functions + OFString pathCopy = path; + if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) + return findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); + else if (obj->ident() == EVR_SQ) + return findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); + else + return EC_IllegalParameter; +} // Permits deleting DICOM object hierarchies based on a path string -OFCondition DcmPathProcessor::findOrDeletePath(DcmObject* obj, - const OFString& path, - Uint32& numDeleted) +OFCondition DcmPathProcessor::findOrDeletePath(DcmObject* obj, const OFString& path, Uint32& numDeleted) { - // check input parameters - if ( (obj == NULL) || path.empty()) - return EC_IllegalParameter; - numDeleted = 0; - if (!m_itemWildcardsEnabled) - { - if (path.find('*') != OFString_npos) - { - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); - } - } - - // search - m_createIfNecessary = OFFalse; - OFString pathCopy = path; - OFCondition result; - clear(); - if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) - result = findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); - else if (obj->ident() == EVR_SQ) - result = findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); - else - return EC_IllegalParameter; - if (result.bad()) return result; - - // check results - OFList resultPaths; - Uint32 numPaths = getResults(resultPaths); - if (numPaths == 0) return EC_IllegalCall; // should never happen at this point - OFListIterator(DcmPath*) pathIt = resultPaths.begin(); - OFListIterator(DcmPath*) endIt = resultPaths.end(); - while (pathIt != endIt) - { - // get last item/element from path which should be deleted - DcmPathNode* nodeToDelete = (*pathIt)->back(); - if ( (nodeToDelete == NULL) || (nodeToDelete->m_obj == NULL) ) return EC_IllegalCall; - - // if it's not an item, delete element from item. - // deletes DICOM content of node but not node itself (done later) - if (nodeToDelete->m_obj->ident() != EVR_item) - { - result = deleteLastElemFromPath(obj, *pathIt, nodeToDelete); - } - // otherwise we need to delete an item from a sequence + // check input parameters + if ((obj == NULL) || path.empty()) + return EC_IllegalParameter; + numDeleted = 0; + if (!m_itemWildcardsEnabled) + { + if (path.find('*') != OFString_npos) + { + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); + } + } + + // search + m_createIfNecessary = OFFalse; + OFString pathCopy = path; + OFCondition result; + clear(); + if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) + result = findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); + else if (obj->ident() == EVR_SQ) + result = findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); else + return EC_IllegalParameter; + if (result.bad()) + return result; + + // check results + OFList resultPaths; + Uint32 numPaths = getResults(resultPaths); + if (numPaths == 0) + return EC_IllegalCall; // should never happen at this point + OFListIterator(DcmPath*) pathIt = resultPaths.begin(); + OFListIterator(DcmPath*) endIt = resultPaths.end(); + while (pathIt != endIt) { - result = deleteLastItemFromPath(obj, *pathIt, nodeToDelete); + // get last item/element from path which should be deleted + DcmPathNode* nodeToDelete = (*pathIt)->back(); + if ((nodeToDelete == NULL) || (nodeToDelete->m_obj == NULL)) + return EC_IllegalCall; + + // if it's not an item, delete element from item. + // deletes DICOM content of node but not node itself (done later) + if (nodeToDelete->m_obj->ident() != EVR_item) + { + result = deleteLastElemFromPath(obj, *pathIt, nodeToDelete); + } + // otherwise we need to delete an item from a sequence + else + { + result = deleteLastItemFromPath(obj, *pathIt, nodeToDelete); + } + if (result.bad()) + return result; + // if success, remove node from path and clear node memory + (*pathIt)->deleteBackNode(); + numDeleted++; + pathIt++; } - if (result.bad()) return result; - // if success, remove node from path and clear node memory - (*pathIt)->deleteBackNode(); - numDeleted++; - pathIt++; - } - return result; + return result; } - // Get results of a an operation started before (e.g. findOrCreatePath()) Uint32 DcmPathProcessor::getResults(OFList& searchResults) { - if (m_results.size() > 0) - { - // explicitly copy (shallow) - OFListIterator(DcmPath*) it = m_results.begin(); - while (it != m_results.end()) + if (m_results.size() > 0) { - searchResults.push_back(*it); - it++; + // explicitly copy (shallow) + OFListIterator(DcmPath*) it = m_results.begin(); + while (it != m_results.end()) + { + searchResults.push_back(*it); + it++; + } } - } - return OFstatic_cast(Uint32, m_results.size()); + return OFstatic_cast(Uint32, m_results.size()); } // applies a string path (optionally with value) to a dataset -OFCondition DcmPathProcessor::applyPathWithValue(DcmDataset* dataset, - const OFString& overrideKey) +OFCondition DcmPathProcessor::applyPathWithValue(DcmDataset* dataset, const OFString& overrideKey) { - if (dataset == NULL) return EC_IllegalCall; - if (overrideKey.empty()) return EC_Normal; - OFString path = overrideKey; - OFString value; - size_t pos = path.find('='); - // separate tag from value if there is one - if (pos != OFString_npos) - { - value = path.substr(pos + 1); // value now contains value - path.erase(pos); // pure path without value - } - clear(); - - // create path - OFCondition result = findOrCreatePath(dataset, path, OFTrue /* create if necessary */); - if (result.bad()) - return result; + if (dataset == NULL) + return EC_IllegalCall; + if (overrideKey.empty()) + return EC_Normal; + OFString path = overrideKey; + OFString value; + size_t pos = path.find('='); + // separate tag from value if there is one + if (pos != OFString_npos) + { + value = path.substr(pos + 1); // value now contains value + path.erase(pos); // pure path without value + } + clear(); - // prepare for value insertion - OFListConstIterator(DcmPath*) it = m_results.begin(); - OFListConstIterator(DcmPath*) endList = m_results.end(); - DcmPathNode* last = (*it)->back(); - if (last == NULL) return EC_IllegalCall; - // if value is specified, be sure path does not end with item - if ( !last->m_obj->isLeaf() ) - { - if (value.empty()) - return EC_Normal; - else - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot insert value into path ending with item or sequence"); - } - // insert value into each element affected by path - while (it != endList) - { - last = (*it)->back(); - if (last == NULL) return EC_IllegalCall; - DcmElement* elem = OFstatic_cast(DcmElement*, last->m_obj); - if (elem == NULL) return EC_IllegalCall; - result = elem->putString(value.c_str()); + // create path + OFCondition result = findOrCreatePath(dataset, path, OFTrue /* create if necessary */); if (result.bad()) - break; - it++; - } - return result; -} + return result; + // prepare for value insertion + OFListConstIterator(DcmPath*) it = m_results.begin(); + OFListConstIterator(DcmPath*) endList = m_results.end(); + DcmPathNode* last = (*it)->back(); + if (last == NULL) + return EC_IllegalCall; + // if value is specified, be sure path does not end with item + if (!last->m_obj->isLeaf()) + { + if (value.empty()) + return EC_Normal; + else + return makeOFCondition( + OFM_dcmdata, 25, OF_error, "Cannot insert value into path ending with item or sequence"); + } + // insert value into each element affected by path + while (it != endList) + { + last = (*it)->back(); + if (last == NULL) + return EC_IllegalCall; + DcmElement* elem = OFstatic_cast(DcmElement*, last->m_obj); + if (elem == NULL) + return EC_IllegalCall; + result = elem->putString(value.c_str()); + if (result.bad()) + break; + it++; + } + return result; +} // Resets status (including results) of DcmPathProcessor and frees corresponding memory void DcmPathProcessor::clear() { - while (m_results.size() != 0) - { - DcmPath* result = m_results.front(); - if (result != NULL) + while (m_results.size() != 0) { - delete result; - result = NULL; + DcmPath* result = m_results.front(); + if (result != NULL) + { + delete result; + result = NULL; + } + m_results.pop_front(); } - m_results.pop_front(); - } - while (m_currentPath.size() != 0) - { - DcmPathNode* node = m_currentPath.front(); - if (node != NULL) + while (m_currentPath.size() != 0) { - delete node; - node = NULL; + DcmPathNode* node = m_currentPath.front(); + if (node != NULL) + { + delete node; + node = NULL; + } + m_currentPath.pop_front(); } - m_currentPath.pop_front(); - } - } - // Destructor, frees memory by calling clear() DcmPathProcessor::~DcmPathProcessor() { - clear(); + clear(); } - /* protected helper functions */ // Helper function that deletes last DICOM element from a path from the DICOM hierarchy -OFCondition DcmPathProcessor::deleteLastElemFromPath(DcmObject* objSearchedIn, - DcmPath* path, - DcmPathNode* toDelete) +OFCondition DcmPathProcessor::deleteLastElemFromPath(DcmObject* objSearchedIn, DcmPath* path, DcmPathNode* toDelete) { - // item containing the element to delete - DcmItem* containingItem = NULL; - if ( path->size() == 1) - { - // if we have only a single elem in path, given object must be cont. item - if ( (objSearchedIn->ident() != EVR_item) && (objSearchedIn->ident() != EVR_dataset) ) - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); - containingItem = OFstatic_cast(DcmItem*, objSearchedIn); - } - else - { - // get containing item from path which is the penultimate in the path - OFListIterator(DcmPathNode*) temp = path->end(); - temp--; temp--; - if (*temp == NULL) return EC_IllegalCall; // never happens here... - if ( (*temp)->m_obj == NULL ) return EC_IllegalCall; - if ( (*temp)->m_obj->ident() != EVR_item) // (no test for dataset needed) - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); - containingItem = OFstatic_cast(DcmItem*, (*temp)->m_obj); - } - if (containingItem == NULL) return EC_IllegalCall; - OFCondition result = containingItem->findAndDeleteElement(toDelete->m_obj->getTag(), OFFalse, OFFalse); - return result; + // item containing the element to delete + DcmItem* containingItem = NULL; + if (path->size() == 1) + { + // if we have only a single elem in path, given object must be cont. item + if ((objSearchedIn->ident() != EVR_item) && (objSearchedIn->ident() != EVR_dataset)) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); + containingItem = OFstatic_cast(DcmItem*, objSearchedIn); + } + else + { + // get containing item from path which is the penultimate in the path + OFListIterator(DcmPathNode*) temp = path->end(); + temp--; + temp--; + if (*temp == NULL) + return EC_IllegalCall; // never happens here... + if ((*temp)->m_obj == NULL) + return EC_IllegalCall; + if ((*temp)->m_obj->ident() != EVR_item) // (no test for dataset needed) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); + containingItem = OFstatic_cast(DcmItem*, (*temp)->m_obj); + } + if (containingItem == NULL) + return EC_IllegalCall; + OFCondition result = containingItem->findAndDeleteElement(toDelete->m_obj->getTag(), OFFalse, OFFalse); + return result; } - // Helper function that deletes last DICOM item from a path from the DICOM hierarchy -OFCondition DcmPathProcessor::deleteLastItemFromPath(DcmObject* objSearchedIn, - DcmPath* path, - DcmPathNode* toDelete) +OFCondition DcmPathProcessor::deleteLastItemFromPath(DcmObject* objSearchedIn, DcmPath* path, DcmPathNode* toDelete) { - DcmSequenceOfItems* containingSeq = NULL; - if ( path->size() == 1) - { - // if we have only a single elem in path, given object must be cont. item - if (objSearchedIn->ident() != EVR_SQ) - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); - containingSeq = OFstatic_cast(DcmSequenceOfItems*, objSearchedIn); - } - else - { - // get containing item from path which is the penultimate in the path - OFListIterator(DcmPathNode*) temp = path->end(); - temp--; temp--; - if (*temp == NULL) return EC_IllegalCall; // never happens here... - if ( (*temp)->m_obj == NULL ) return EC_IllegalCall; - if ( (*temp)->m_obj->ident() != EVR_SQ) - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); - containingSeq = OFstatic_cast(DcmSequenceOfItems*, (*temp)->m_obj); - } - if (containingSeq == NULL ) return EC_IllegalCall; - DcmItem* item2BDeleted = containingSeq->remove(OFstatic_cast(DcmItem*, toDelete->m_obj)); - if ( item2BDeleted == NULL ) - return EC_IllegalCall; // should not happen here... - delete item2BDeleted; item2BDeleted = NULL; - return EC_Normal; + DcmSequenceOfItems* containingSeq = NULL; + if (path->size() == 1) + { + // if we have only a single elem in path, given object must be cont. item + if (objSearchedIn->ident() != EVR_SQ) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); + containingSeq = OFstatic_cast(DcmSequenceOfItems*, objSearchedIn); + } + else + { + // get containing item from path which is the penultimate in the path + OFListIterator(DcmPathNode*) temp = path->end(); + temp--; + temp--; + if (*temp == NULL) + return EC_IllegalCall; // never happens here... + if ((*temp)->m_obj == NULL) + return EC_IllegalCall; + if ((*temp)->m_obj->ident() != EVR_SQ) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); + containingSeq = OFstatic_cast(DcmSequenceOfItems*, (*temp)->m_obj); + } + if (containingSeq == NULL) + return EC_IllegalCall; + DcmItem* item2BDeleted = containingSeq->remove(OFstatic_cast(DcmItem*, toDelete->m_obj)); + if (item2BDeleted == NULL) + return EC_IllegalCall; // should not happen here... + delete item2BDeleted; + item2BDeleted = NULL; + return EC_Normal; } - // Helper function that does work for findOrCreatePath() -OFCondition DcmPathProcessor::findOrCreateItemPath(DcmItem* item, - OFString& path) +OFCondition DcmPathProcessor::findOrCreateItemPath(DcmItem* item, OFString& path) { - if (item == NULL) - return EC_IllegalParameter; - - if (path.empty()) - return EC_IllegalParameter; - - OFString restPath(path); - OFCondition status = EC_Normal; - DcmTag tag; - OFString privCreator; - OFBool newlyCreated = OFFalse; // denotes whether an element was created - DcmElement* elem = NULL; - DcmPath* currentResult = NULL; - - // parse tag - status = DcmPath::parseTagFromPath(restPath, tag); - if (status.bad()) - return status; + if (item == NULL) + return EC_IllegalParameter; - // insert element or sequence - if ( !(item->tagExists(tag)) ) // do not to overwrite existing tags - { - if (m_createIfNecessary) - { - // private tags needs special handling, e.g. checking reservation - if (tag.isPrivate() && m_checkPrivateReservations) - { - status = checkPrivateTagReservation(item, tag); - if (status.bad()) return status; - } - elem = DcmItem::newDicomElement(tag); - if (elem == NULL) - return EC_IllegalCall; - status = item->insert(elem, OFTrue); - if (status.bad()) - { - delete elem; elem = NULL; + if (path.empty()) + return EC_IllegalParameter; + + OFString restPath(path); + OFCondition status = EC_Normal; + DcmTag tag; + OFString privCreator; + OFBool newlyCreated = OFFalse; // denotes whether an element was created + DcmElement* elem = NULL; + DcmPath* currentResult = NULL; + + // parse tag + status = DcmPath::parseTagFromPath(restPath, tag); + if (status.bad()) return status; - } - newlyCreated = OFTrue; + + // insert element or sequence + if (!(item->tagExists(tag))) // do not to overwrite existing tags + { + if (m_createIfNecessary) + { + // private tags needs special handling, e.g. checking reservation + if (tag.isPrivate()) + { + if (!tag.isPrivateReservation()) + { + // if this is no reservation, find the private creator and update tag + if (getPrivateCreator(item, tag, privCreator).good() && !privCreator.empty()) + { + tag.setPrivateCreator(privCreator.c_str()); + } + // now that private creator is hopefully set, lookup vr + tag.lookupVRinDictionary(); + // check private reservation if desired + if (m_checkPrivateReservations) + { + status = checkPrivateTagReservation(item, tag.getXTag()); + if (status.bad()) + return status; + } + } + } + // create element for insertion + elem = DcmItem::newDicomElement(tag, privCreator.empty() ? NULL : privCreator.c_str()); + if (elem == NULL) + return EC_IllegalCall; + status = item->insert(elem, OFTrue); + if (status.bad()) + { + delete elem; + elem = NULL; + return status; + } + newlyCreated = OFTrue; + } + else + return EC_TagNotFound; } - else - return EC_TagNotFound; - } - - // get element - status = item->findAndGetElement(tag, elem); - if (status.bad()) - return EC_CorruptedData; // should not happen - - // start recursion if element was a sequence - if (tag.getEVR() == EVR_SQ) - { - DcmSequenceOfItems* seq = NULL; - seq = OFstatic_cast(DcmSequenceOfItems*, elem); - if (!seq) - status = EC_IllegalCall; // should not happen - else + + // get element + status = item->findAndGetElement(tag, elem); + if (status.bad()) + return EC_CorruptedData; // should not happen + + // start recursion if element was a sequence + if (tag.getEVR() == EVR_SQ) + { + DcmSequenceOfItems* seq = NULL; + seq = OFstatic_cast(DcmSequenceOfItems*, elem); + if (!seq) + status = EC_IllegalCall; // should not happen + else + { + // if sequence could be inserted and there is nothing more to do: add current path to results and return + // success + if (restPath.empty()) + { + currentResult = new DcmPath(m_currentPath); + currentResult->append(new DcmPathNode(elem, 0)); + m_results.push_back(currentResult); + return EC_Normal; + } + // start recursion if there is path left + DcmPathNode* node = new DcmPathNode(seq, 0); + m_currentPath.push_back(node); + status = findOrCreateSequencePath(seq, restPath); + m_currentPath.pop_back(); // avoid side effects + delete node; + } + } + else if (restPath.empty()) // we inserted a leaf element: path must be completed { - // if sequence could be inserted and there is nothing more to do: add current path to results and return success - if (restPath.empty()) - { + // add element and add current path to overall results; then return success currentResult = new DcmPath(m_currentPath); - currentResult->append(new DcmPathNode(elem,0)); + currentResult->append(new DcmPathNode(elem, 0)); m_results.push_back(currentResult); return EC_Normal; - } - // start recursion if there is path left - DcmPathNode* node = new DcmPathNode(seq, 0); - m_currentPath.push_back(node); - status = findOrCreateSequencePath(seq, restPath); - m_currentPath.pop_back(); // avoid side effects - delete node; - } - } - else if (restPath.empty()) // we inserted a leaf element: path must be completed - { - // add element and add current path to overall results; then return success - currentResult = new DcmPath(m_currentPath); - currentResult->append(new DcmPathNode(elem, 0)); - m_results.push_back(currentResult); - return EC_Normal; - } - else // we inserted a leaf element but there is path left -> error - status = makeOFCondition(OFM_dcmdata, 25, OF_error, "Invalid Path: Non-sequence tag found with rest path following"); - - // in case of errors: delete result path copy and delete DICOM element if it was newly created - if ( status.bad() && (elem != NULL) ) - { - m_results.remove(currentResult); // remove from search result - if (currentResult) - { - delete currentResult; - currentResult = NULL; } - if (newlyCreated) // only delete from this dataset and memory if newly created ("undo") + else // we inserted a leaf element but there is path left -> error + status = makeOFCondition( + OFM_dcmdata, 25, OF_error, "Invalid Path: Non-sequence tag found with rest path following"); + + // in case of errors: delete result path copy and delete DICOM element if it was newly created + if (status.bad() && (elem != NULL)) { - if (item->findAndDeleteElement(tag).bad()) - delete elem; // delete manually if not found in dataset + m_results.remove(currentResult); // remove from search result + if (currentResult) + { + delete currentResult; + currentResult = NULL; + } + if (newlyCreated) // only delete from this dataset and memory if newly created ("undo") + { + if (item->findAndDeleteElement(tag).bad()) + delete elem; // delete manually if not found in dataset + } + elem = NULL; } - elem = NULL; - } - return status; + return status; } - // Helper function that does work for findOrCreatePath() -OFCondition DcmPathProcessor::findOrCreateSequencePath(DcmSequenceOfItems* seq, - OFString& path) +OFCondition DcmPathProcessor::findOrCreateSequencePath(DcmSequenceOfItems* seq, OFString& path) { - if (seq == NULL) - return EC_IllegalParameter; - - // prepare variables - OFString restPath(path); - OFCondition status = EC_Normal; - DcmItem* resultItem = NULL; - Uint32 itemNo = 0; - Uint32 newlyCreated = 0; // number of items created (appended) (only non-wildcard mode) - Uint32 newPathsCreated = 0; // wildcard mode: number of paths found - - // parse item number - OFBool isWildcard = OFFalse; - status = DcmPath::parseItemNoFromPath(restPath, itemNo, isWildcard); - if (status.bad()) - return status; + if (seq == NULL) + return EC_IllegalParameter; + + // prepare variables + OFString restPath(path); + OFCondition status = EC_Normal; + DcmItem* resultItem = NULL; + Uint32 itemNo = 0; + Uint32 newlyCreated = 0; // number of items created (appended) (only non-wildcard mode) + Uint32 newPathsCreated = 0; // wildcard mode: number of paths found + + // parse item number + OFBool isWildcard = OFFalse; + status = DcmPath::parseItemNoFromPath(restPath, itemNo, isWildcard); + if (status.bad()) + return status; - // wildcard code: add result path for every matching item - if (isWildcard) - { - // if there are no items -> no results are found - Uint32 numItems = OFstatic_cast(Uint32, seq->card()); - if (numItems == 0) + // wildcard code: add result path for every matching item + if (isWildcard) { - if (!m_createIfNecessary) - return EC_TagNotFound; - else - return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot insert unspecified number (wildcard) of items into sequence"); - } - - // copy every item to result - for (itemNo = 0; itemNo < numItems; itemNo++) - { - DcmItem* oneItem = seq->getItem(itemNo); - /* if we found an item that matches, copy current result path, then - add the item found and finally start recursive search for - that item. - */ - if (oneItem != NULL) - { - // if the item was the last thing to parse, add list to results and return - if (restPath.empty()) + // if there are no items -> no results are found + Uint32 numItems = OFstatic_cast(Uint32, seq->card()); + if (numItems == 0) { - DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); - DcmPath* currentResult = new DcmPath(m_currentPath); - currentResult->append(itemNode); - m_results.push_back(currentResult); - newPathsCreated++; + if (!m_createIfNecessary) + return EC_TagNotFound; + else + return makeOFCondition( + OFM_dcmdata, 25, OF_error, "Cannot insert unspecified number (wildcard) of items into sequence"); } - // else there is path left: continue searching in the new item - else + + // copy every item to result + for (itemNo = 0; itemNo < numItems; itemNo++) { - DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); - m_currentPath.push_back(itemNode); - status = findOrCreateItemPath(oneItem, restPath); - m_currentPath.pop_back(); // avoid side effects - delete itemNode; itemNode = NULL; - if (status.bad()) // we did not find the path in that item - { - if (status != EC_TagNotFound) - return status; - } - else - { - newPathsCreated++; - } + DcmItem* oneItem = seq->getItem(itemNo); + /* if we found an item that matches, copy current result path, then + add the item found and finally start recursive search for + that item. + */ + if (oneItem != NULL) + { + // if the item was the last thing to parse, add list to results and return + if (restPath.empty()) + { + DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); + DcmPath* currentResult = new DcmPath(m_currentPath); + currentResult->append(itemNode); + m_results.push_back(currentResult); + newPathsCreated++; + } + // else there is path left: continue searching in the new item + else + { + DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); + m_currentPath.push_back(itemNode); + status = findOrCreateItemPath(oneItem, restPath); + m_currentPath.pop_back(); // avoid side effects + delete itemNode; + itemNode = NULL; + if (status.bad()) // we did not find the path in that item + { + if (status != EC_TagNotFound) + return status; + } + else + { + newPathsCreated++; + } + } + } + else // should be possible to get every item, however... + return EC_IllegalCall; } - } - else // should be possible to get every item, however... - return EC_IllegalCall; + // if there was at least one result, success can be returned + if (newPathsCreated != 0) + { + return EC_Normal; + } + else + return EC_TagNotFound; } - // if there was at least one result, success can be returned - if (newPathsCreated != 0) + + /* no wildcard, just select single item or create it if necessary */ + + // if item already exists, just grab a reference + if (itemNo < seq->card()) + resultItem = seq->getItem(itemNo); + // if item does not exist, create new if desired + else if (m_createIfNecessary) { - return EC_Normal; + // create and insert items until desired item count is reached + while ((seq->card() <= itemNo) || (status.bad())) + { + resultItem = new DcmItem(); + if (!resultItem) + return EC_MemoryExhausted; + status = seq->insert(resultItem); + if (status.bad()) + delete resultItem; + else + newlyCreated++; + } } + // item does not exist and should not be created newly, return "path not found" else - return EC_TagNotFound; - } - - - /* no wildcard, just select single item or create it if necessary */ - - // if item already exists, just grab a reference - if (itemNo < seq->card()) - resultItem = seq->getItem(itemNo); - // if item does not exist, create new if desired - else if (m_createIfNecessary) - { - // create and insert items until desired item count is reached - while ( (seq->card() <= itemNo) || (status.bad()) ) - { - resultItem = new DcmItem(); - if (!resultItem) return EC_MemoryExhausted; - status = seq->insert(resultItem); - if (status.bad()) - delete resultItem; - else - newlyCreated++; - } - } - // item does not exist and should not be created newly, return "path not found" - else - return EC_TagNotFound; - - // at this point, the item has been obtained and everything is fine so far - - // finding/creating the path was successful. now check whether there is more to do - if (!restPath.empty()) - { - // push new item to result path and continue - DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); - m_currentPath.push_back(itemNode); - status = findOrCreateItemPath(resultItem, restPath); - m_currentPath.pop_back(); // avoid side effects to input parameter - delete itemNode; itemNode = NULL; - // in case of no success, delete any items that were newly created and return error - if (status.bad()) + return EC_TagNotFound; + + // at this point, the item has been obtained and everything is fine so far + + // finding/creating the path was successful. now check whether there is more to do + if (!restPath.empty()) { - for (Uint32 i=newlyCreated; i > 0; i--) - { - DcmItem* todelete = seq->remove(i - 1); - if (todelete != NULL) + // push new item to result path and continue + DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); + m_currentPath.push_back(itemNode); + status = findOrCreateItemPath(resultItem, restPath); + m_currentPath.pop_back(); // avoid side effects to input parameter + delete itemNode; + itemNode = NULL; + // in case of no success, delete any items that were newly created and return error + if (status.bad()) { - delete todelete; - todelete = NULL; + for (Uint32 i = newlyCreated; i > 0; i--) + { + DcmItem* todelete = seq->remove(i - 1); + if (todelete != NULL) + { + delete todelete; + todelete = NULL; + } + } + return status; } - } - return status; - } - } - else // finally everything was successful - { - DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); - m_currentPath.push_back(itemNode); - m_results.push_back(new DcmPath(m_currentPath)); - m_currentPath.pop_back(); // avoid side effects - delete itemNode; itemNode = NULL; - status = EC_Normal; - } - return status; + } + else // finally everything was successful + { + DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); + m_currentPath.push_back(itemNode); + m_results.push_back(new DcmPath(m_currentPath)); + m_currentPath.pop_back(); // avoid side effects + delete itemNode; + itemNode = NULL; + status = EC_Normal; + } + return status; } - -DcmTagKey DcmPathProcessor::calcPrivateReservationTag(const DcmTagKey &privateKey) +DcmTagKey DcmPathProcessor::calcPrivateReservationTag(const DcmTagKey& privateKey) { - DcmTagKey reservationTag(0xFFFF, 0xFFFF); - // if not a private key is given return "error" - if (!privateKey.isPrivate()) + DcmTagKey reservationTag(0xFFFF, 0xFFFF); + // if not a private key is given return "error" + if (!privateKey.isPrivate()) + return reservationTag; + // if the private key given is already a reservation key, return it + if (privateKey.isPrivateReservation()) + return privateKey; + + // Calculate corresponding private creator element + Uint16 elemNo = privateKey.getElement(); + // Get yz from given element number wxyz, groups stays the same + elemNo = OFstatic_cast(Uint16, elemNo >> 8); + reservationTag.setGroup(privateKey.getGroup()); + reservationTag.setElement(elemNo); return reservationTag; - // if the private key given is already a reservation key, return it - if (privateKey.isPrivateReservation()) - return privateKey; - - // Calculate corresponding private creator element - Uint16 elemNo = privateKey.getElement(); - // Get yz from given element number wxyz, groups stays the same - elemNo = OFstatic_cast(Uint16, elemNo >> 8); - reservationTag.setGroup(privateKey.getGroup()); - reservationTag.setElement(elemNo); - return reservationTag; } - -OFCondition DcmPathProcessor::checkPrivateTagReservation(DcmItem* item, - const DcmTagKey& tagKey, - const OFString& privateCreator) +OFCondition DcmPathProcessor::getPrivateCreator(DcmItem* item, const DcmTagKey& tagKey, OFString& privateCreator) { - // if this is already a private reservation, there is nothing to do - if (!tagKey.isPrivateReservation()) - { - DcmTagKey reservationKey = calcPrivateReservationTag(tagKey); - if (reservationKey == DCM_UndefinedTagKey) - { - OFString msg("Unable to compute private reservation for tag: "); msg += tagKey.toString(); - return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); - } - if (!item->tagExists(reservationKey)) + DcmTagKey reservationKey; + if (!tagKey.isPrivateReservation()) { - OFString msg("Private reservation missing for tag: "); msg += tagKey.toString(); - return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + reservationKey = calcPrivateReservationTag(tagKey); + if (reservationKey == DCM_UndefinedTagKey) + { + OFString msg("Unable to compute private reservation for tag: "); + msg += tagKey.toString(); + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + } + if (!item->tagExists(reservationKey)) + { + return EC_TagNotFound; + } + return item->findAndGetOFString(reservationKey, privateCreator); } else + return EC_IllegalCall; +} + +OFCondition +DcmPathProcessor::checkPrivateTagReservation(DcmItem* item, const DcmTagKey& tagKey, const OFString& privateCreator) +{ + OFString actualPrivateCreator; + OFCondition result = getPrivateCreator(item, tagKey, actualPrivateCreator); + if (result.bad() || actualPrivateCreator.empty()) { - // set private creator for new element - OFString actualPrivateCreator; - if (item->findAndGetOFString(reservationKey, actualPrivateCreator).bad() || (actualPrivateCreator.empty())) - { - OFString msg = "Invalid or empty private creator tag: "; msg += reservationKey.toString(); + OFString msg = "Invalid or empty private creator tag: "; + msg += calcPrivateReservationTag(tagKey).toString(); return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); - } - else if (!privateCreator.empty()) - { + } + else if (!privateCreator.empty()) + { // check whether private creator is correct if (actualPrivateCreator != privateCreator) { - OFString msg = "Private creator string ("; msg += actualPrivateCreator; msg += ") other than expected ( "; msg += privateCreator; msg += privateCreator; - return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + OFString msg = "Private creator string ("; + msg += actualPrivateCreator; + msg += ") other than expected ( "; + msg += privateCreator; + msg += privateCreator; + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); } - } } - } - return EC_Normal; -} - - - -OFCondition DcmPathProcessor::checkPrivateTagReservation(DcmItem* item /* in */, - DcmTag& tag /* inout */, - const OFString& privateCreator) -{ - OFCondition result = checkPrivateTagReservation(item, tag.getXTag(), privateCreator); - if (result.good()) - { - // tell tag its private creator and VR - tag.setPrivateCreator(privateCreator.c_str()); - tag.lookupVRinDictionary(); // not done automatically when saving - } - return result; + return EC_Normal; } - diff --git a/dcmdata/libsrc/dcpixel.cc b/dcmdata/libsrc/dcpixel.cc index 7c402499..7d1e6155 100644 --- a/dcmdata/libsrc/dcpixel.cc +++ b/dcmdata/libsrc/dcpixel.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2019, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -26,6 +26,7 @@ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcjson.h" // // class DcmRepresentationEntry @@ -89,7 +90,8 @@ DcmPixelData::DcmPixelData( { repListEnd = repList.end(); current = original = repListEnd; - if (getTag().getEVR() == EVR_ox) setTagVR(EVR_OW); + if ((getTag().getEVR() == EVR_ox) || (getTag().getEVR() == EVR_px)) + setTagVR(EVR_OW); unencapsulatedVR = getTag().getEVR(); recalcVR(); } @@ -441,13 +443,20 @@ DcmPixelData::decode( DcmStack & pixelStack) { if (existUnencapsulated) return EC_Normal; - OFCondition l_error = DcmCodecList::decode(fromType, fromParam, fromPixSeq, *this, pixelStack); + OFBool removeOldPixelRepresentation = OFFalse; + OFCondition l_error = DcmCodecList::decode(fromType, fromParam, fromPixSeq, *this, pixelStack, removeOldPixelRepresentation); if (l_error.good()) { existUnencapsulated = OFTrue; current = repListEnd; setVR(EVR_OW); recalcVR(); + + // the codec has indicated that the image pixel module has been modified + // in a way that may affect the validity of the old representation of pixel data. + // Thus, we cannot just switch back to the old representation. + // Thus, remove old representation(s). + if (removeOldPixelRepresentation) removeAllButCurrentRepresentations(); } else { @@ -472,10 +481,11 @@ DcmPixelData::encode( if (toType.isEncapsulated()) { DcmPixelSequence * toPixSeq = NULL; + OFBool removeOldPixelRepresentation = OFFalse; if (fromType.isEncapsulated()) { l_error = DcmCodecList::encode(fromType.getXfer(), fromParam, fromPixSeq, - toType.getXfer(), toParam, toPixSeq, pixelStack); + toType.getXfer(), toParam, toPixSeq, pixelStack, removeOldPixelRepresentation); } else { @@ -485,7 +495,7 @@ DcmPixelData::encode( if (l_error == EC_Normal) { l_error = DcmCodecList::encode(fromType.getXfer(), pixelData, length, - toType.getXfer(), toParam, toPixSeq, pixelStack); + toType.getXfer(), toParam, toPixSeq, pixelStack, removeOldPixelRepresentation); } } @@ -494,6 +504,11 @@ DcmPixelData::encode( current = insertRepresentationEntry( new DcmRepresentationEntry(toType.getXfer(), toParam, toPixSeq)); recalcVR(); + // the codec has indicated that the image pixel module has been modified + // in a way that may affect the validity of the old representation of pixel data. + // Thus, we cannot just switch back to the old representation, but have + // to actually decode in this case. Thus, remove old representation(s). + if (removeOldPixelRepresentation) removeAllButCurrentRepresentations(); } else delete toPixSeq; // if it was possible to convert one encapsulated syntax into @@ -1270,3 +1285,66 @@ OFBool DcmPixelData::writeUnencapsulated(const E_TransferSyntax xfer) return existUnencapsulated && isNested(); } + + +OFCondition DcmPixelData::writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format) +{ + + // check if we have an empty uncompressed value field. + // We never encode that as BulkDataURI. + OFBool emptyValue = OFFalse; + if ((current == repListEnd) && existUnencapsulated && (getLengthField() == 0)) + { + emptyValue = OFTrue; + } + + // now check if the pixel data will be written as + // BulkDataURI, which is possible for both uncompressed + // and encapsulated pixel data. + OFString value; + if ((! emptyValue) && format.asBulkDataURI(getTag(), value)) + { + /* write JSON Opener */ + writeJsonOpener(out, format); + + /* return defined BulkDataURI */ + format.printBulkDataURIPrefix(out); + DcmJsonFormat::printString(out, value); + + /* write JSON Closer */ + writeJsonCloser(out, format); + return EC_Normal; + } + + // No bulk data URI, we're supposed to write as InlineBinary. + // This is only defined for uncompressed data, not for any of the + // encapsulated encodings. + + // check the current pixel data representation + if ((current == repListEnd) && existUnencapsulated) + { + // current pixel data representation is uncompressed (and available). + + /* write JSON Opener */ + writeJsonOpener(out, format); + + /* for an empty value field, we do not need to do anything */ + if (getLengthField() > 0) + { + /* encode binary data as Base64 */ + format.printInlineBinaryPrefix(out); + out << "\""; + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + out << "\""; + } + /* write JSON Closer */ + writeJsonCloser(out, format); + return EC_Normal; + } + + // pixel data is encapsulated, return error + return EC_CannotWriteJsonInlineBinary; +} diff --git a/dcmdata/libsrc/dcpixseq.cc b/dcmdata/libsrc/dcpixseq.cc index d8cdcf1a..42d1f6b6 100644 --- a/dcmdata/libsrc/dcpixseq.cc +++ b/dcmdata/libsrc/dcpixseq.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2017, OFFIS e.V. + * Copyright (C) 1994-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -240,12 +240,18 @@ OFCondition DcmPixelSequence::insert(DcmPixelItem *item, errorFlag = EC_Normal; if (item != NULL) { - itemList->seek_to(where); - itemList->insert(item); - if (where < itemList->card()) - DCMDATA_TRACE("DcmPixelSequence::insert() Item at position " << where << " inserted"); - if (where >= itemList->card()) + // special case: last position + if (where == DCM_EndOfListIndex) + { + // insert at end of list (avoid seeking) + itemList->append(item); DCMDATA_TRACE("DcmPixelSequence::insert() Item at last position inserted"); + } else { + // insert after "where" + itemList->seek_to(where); + itemList->insert(item); + DCMDATA_TRACE("DcmPixelSequence::insert() Item at position " << where << " inserted"); + } // check whether the new item already has a parent if (item->getParent() != NULL) { diff --git a/dcmdata/libsrc/dcrleccd.cc b/dcmdata/libsrc/dcrleccd.cc index 61fde6be..ffdd1411 100644 --- a/dcmdata/libsrc/dcrleccd.cc +++ b/dcmdata/libsrc/dcrleccd.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2019, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -63,7 +63,8 @@ OFCondition DcmRLECodecDecoder::decode( DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const + const DcmStack& objStack, + OFBool& /* removeOldRep */) const { OFCondition result = EC_Normal; @@ -704,7 +705,8 @@ OFCondition DcmRLECodecDecoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* pixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we are a decoder only return EC_IllegalCall; @@ -718,7 +720,8 @@ OFCondition DcmRLECodecDecoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we don't support re-coding for now. return EC_IllegalCall; diff --git a/dcmdata/libsrc/dcrlecce.cc b/dcmdata/libsrc/dcrlecce.cc index 6d54eff0..30a5a64c 100644 --- a/dcmdata/libsrc/dcrlecce.cc +++ b/dcmdata/libsrc/dcrlecce.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2016, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -71,7 +71,8 @@ OFCondition DcmRLECodecEncoder::decode( DcmPixelSequence * /* pixSeq */, DcmPolymorphOBOW& /* uncompressedPixelData */, const DcmCodecParameter * /* cp */, - const DcmStack& /* objStack */) const + const DcmStack& /* objStack */, + OFBool& /* removeOldRep */ ) const { // we are an encoder only return EC_IllegalCall; @@ -101,7 +102,8 @@ OFCondition DcmRLECodecEncoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack& /* objStack */, + OFBool& /* removeOldRep */ ) const { // we don't support re-coding for now. return EC_IllegalCall; @@ -114,7 +116,8 @@ OFCondition DcmRLECodecEncoder::encode( const DcmRepresentationParameter * /* toRepParam */ , DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const + DcmStack& objStack, + OFBool& /* removeOldRep */ ) const { OFCondition result = EC_Normal; diff --git a/dcmdata/libsrc/dcsequen.cc b/dcmdata/libsrc/dcsequen.cc index af8f7dbe..840cf639 100644 --- a/dcmdata/libsrc/dcsequen.cc +++ b/dcmdata/libsrc/dcsequen.cc @@ -484,11 +484,9 @@ Uint32 DcmSequenceOfItems::getLength(const E_TransferSyntax xfer, Uint32 sublen = 0; if (!itemList->empty()) { - DcmItem *dI; itemList->seek(ELP_first); do { - dI = OFstatic_cast(DcmItem *, itemList->get()); - sublen = dI->calcElementLength(xfer, enctype); + sublen = itemList->get()->calcElementLength(xfer, enctype); /* explicit length: be sure that total size of contained elements fits into sequence's 32 Bit length field. If not, switch encoding automatically to undefined length for this sequence. Nevertheless, any contained items will be @@ -1046,15 +1044,25 @@ OFCondition DcmSequenceOfItems::insert(DcmItem *item, errorFlag = EC_Normal; if (item != NULL) { - itemList->seek_to(where); - // insert before or after "where" - E_ListPos whichSide = (before) ? (ELP_prev) : (ELP_next); - itemList->insert(item, whichSide); + // special case: last position if (where == DCM_EndOfListIndex) { + if (before) + { + // insert before end of list + itemList->seek(ELP_last); + itemList->prepend(item); + } else { + // insert at end of list + itemList->append(item); + } DCMDATA_TRACE("DcmSequenceOfItems::insert() Item inserted " << (before ? "before" : "after") << " last position"); } else { + itemList->seek_to(where); + // insert before or after "where" + E_ListPos whichSide = (before) ? (ELP_prev) : (ELP_next); + itemList->insert(item, whichSide); DCMDATA_TRACE("DcmSequenceOfItems::insert() Item inserted " << (before ? "before" : "after") << " position " << where); } diff --git a/dcmdata/libsrc/dcswap.cc b/dcmdata/libsrc/dcswap.cc index 37fa4a7e..278b78f1 100644 --- a/dcmdata/libsrc/dcswap.cc +++ b/dcmdata/libsrc/dcswap.cc @@ -28,8 +28,8 @@ OFCondition swapIfNecessary(const E_ByteOrder newByteOrder, const size_t valWidth) /* * This function swaps byteLength bytes in value if newByteOrder and oldByteOrder - * differ from each other. In case bytes have to be swapped, these bytes are seperated - * in valWidth elements which will be swapped seperately. + * differ from each other. In case bytes have to be swapped, these bytes are separated + * in valWidth elements which will be swapped separately. * * Parameters: * newByteOrder - [in] The new byte ordering (little or big endian). @@ -70,8 +70,8 @@ OFCondition swapIfNecessary(const E_ByteOrder newByteOrder, void swapBytes(void * value, const Uint32 byteLength, const size_t valWidth) /* - * This function swaps byteLength bytes in value. These bytes are seperated - * in valWidth elements which will be swapped seperately. + * This function swaps byteLength bytes in value. These bytes are separated + * in valWidth elements which will be swapped separately. * * Parameters: * value - [in] Array that contains the actual bytes which might have to be swapped. diff --git a/dcmdata/libsrc/dcuid.cc b/dcmdata/libsrc/dcuid.cc index 55469ac7..6e2cb902 100644 --- a/dcmdata/libsrc/dcuid.cc +++ b/dcmdata/libsrc/dcuid.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -139,6 +139,9 @@ static const UIDNameMap uidNameMap[] = { { UID_MPEG4StereoHighProfileLevel4_2TransferSyntax, "MPEG4StereoHighProfile/Level4.2" }, { UID_HEVCMainProfileLevel5_1TransferSyntax, "HEVCMainProfile/Level5.1" }, { UID_HEVCMain10ProfileLevel5_1TransferSyntax, "HEVCMain10Profile/Level5.1" }, + { UID_SMPTEST2110_20_UncompressedProgressiveActiveVideoTransferSyntax, "SMPTEST2110-20:UncompressedProgressiveActiveVideo" }, + { UID_SMPTEST2110_20_UncompressedInterlacedActiveVideoTransferSyntax, "SMPTEST2110-20:UncompressedInterlacedActiveVideo" }, + { UID_SMPTEST2110_30_PCMDigitalAudioTransferSyntax, "SMPTEST2110-30:PCMDigitalAudio" }, { UID_RFC2557MIMEEncapsulationTransferSyntax, "RFC2557MIMEEncapsulation" }, { UID_XMLEncodingTransferSyntax, "XMLEncoding" }, { UID_PrivateGE_LEI_WithBigEndianPixelDataTransferSyntax, "PrivateGELittleEndianImplicitWithBigEndianPixelData" }, @@ -153,10 +156,12 @@ static const UIDNameMap uidNameMap[] = { { UID_BasicTextSRStorage, "BasicTextSRStorage" }, { UID_BasicVoiceAudioWaveformStorage, "BasicVoiceAudioWaveformStorage" }, { UID_BlendingSoftcopyPresentationStateStorage, "BlendingSoftcopyPresentationStateStorage" }, + { UID_BodyPositionWaveformStorage, "BodyPositionWaveformStorage" }, { UID_BreastProjectionXRayImageStorageForPresentation, "BreastProjectionXRayImageStorageForPresentation" }, { UID_BreastProjectionXRayImageStorageForProcessing, "BreastProjectionXRayImageStorageForProcessing" }, { UID_BreastTomosynthesisImageStorage, "BreastTomosynthesisImageStorage" }, { UID_CardiacElectrophysiologyWaveformStorage, "CardiacElectrophysiologyWaveformStorage" }, + { UID_CArmPhotonElectronRadiationRecordStorage, "CArmPhotonElectronRadiationRecordStorage" }, { UID_CArmPhotonElectronRadiationStorage, "CArmPhotonElectronRadiationStorage" }, { UID_ChestCADSRStorage, "ChestCADSRStorage" }, { UID_ColonCADSRStorage, "ColonCADSRStorage" }, @@ -172,13 +177,18 @@ static const UIDNameMap uidNameMap[] = { { UID_CTImageStorage, "CTImageStorage" }, { UID_CTPerformedProcedureProtocolStorage, "CTPerformedProcedureProtocolStorage" }, { UID_DeformableSpatialRegistrationStorage, "DeformableSpatialRegistrationStorage" }, + { UID_DermoscopicPhotographyImageStorage, "DermoscopicPhotographyImageStorage" }, { UID_DigitalIntraOralXRayImageStorageForPresentation, "DigitalIntraOralXRayImageStorageForPresentation" }, { UID_DigitalIntraOralXRayImageStorageForProcessing, "DigitalIntraOralXRayImageStorageForProcessing" }, { UID_DigitalMammographyXRayImageStorageForPresentation, "DigitalMammographyXRayImageStorageForPresentation" }, { UID_DigitalMammographyXRayImageStorageForProcessing, "DigitalMammographyXRayImageStorageForProcessing" }, { UID_DigitalXRayImageStorageForPresentation, "DigitalXRayImageStorageForPresentation" }, { UID_DigitalXRayImageStorageForProcessing, "DigitalXRayImageStorageForProcessing" }, + { UID_ElectromyogramWaveformStorage, "ElectromyogramWaveformStorage" }, + { UID_ElectrooculogramWaveformStorage, "ElectrooculogramWaveformStorage" }, { UID_EncapsulatedCDAStorage, "EncapsulatedCDAStorage" }, + { UID_EncapsulatedMTLStorage, "EncapsulatedMTLStorage" }, + { UID_EncapsulatedOBJStorage, "EncapsulatedOBJStorage" }, { UID_EncapsulatedPDFStorage, "EncapsulatedPDFStorage" }, { UID_EncapsulatedSTLStorage, "EncapsulatedSTLStorage" }, { UID_EnhancedCTImageStorage, "EnhancedCTImageStorage" }, @@ -214,6 +224,7 @@ static const UIDNameMap uidNameMap[] = { { UID_MediaStorageDirectoryStorage, "MediaStorageDirectoryStorage" }, { UID_MRImageStorage, "MRImageStorage" }, { UID_MRSpectroscopyStorage, "MRSpectroscopyStorage" }, + { UID_MultichannelRespiratoryWaveformStorage, "MultichannelRespiratoryWaveformStorage" }, { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "MultiframeGrayscaleByteSecondaryCaptureImageStorage" }, { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "MultiframeGrayscaleWordSecondaryCaptureImageStorage" }, { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "MultiframeSingleBitSecondaryCaptureImageStorage" }, @@ -240,6 +251,9 @@ static const UIDNameMap uidNameMap[] = { { UID_RawDataStorage, "RawDataStorage" }, { UID_RealWorldValueMappingStorage, "RealWorldValueMappingStorage" }, { UID_RespiratoryWaveformStorage, "RespiratoryWaveformStorage" }, + { UID_RoboticArmRadiationStorage, "RoboticArmRadiationStorage" }, + { UID_RoboticRadiationRecordStorage, "RoboticRadiationRecordStorage" }, + { UID_RoutineScalpElectroencephalogramWaveformStorage, "RoutineScalpElectroencephalogramWaveformStorage" }, { UID_RTBeamsDeliveryInstructionStorage, "RTBeamsDeliveryInstructionStorage" }, { UID_RTBeamsTreatmentRecordStorage, "RTBeamsTreatmentRecordStorage" }, { UID_RTBrachyApplicationSetupDeliveryInstructionStorage, "RTBrachyApplicationSetupDeliveryInstructionStorage" }, @@ -250,6 +264,8 @@ static const UIDNameMap uidNameMap[] = { { UID_RTIonPlanStorage, "RTIonPlanStorage" }, { UID_RTPhysicianIntentStorage, "RTPhysicianIntentStorage" }, { UID_RTPlanStorage, "RTPlanStorage" }, + { UID_RTRadiationRecordSetStorage, "RTRadiationRecordSetStorage" }, + { UID_RTRadiationSalvageRecordStorage, "RTRadiationSalvageRecordStorage" }, { UID_RTRadiationSetStorage, "RTRadiationSetStorage" }, { UID_RTSegmentAnnotationStorage, "RTSegmentAnnotationStorage" }, { UID_RTStructureSetStorage, "RTStructureSetStorage" }, @@ -258,6 +274,7 @@ static const UIDNameMap uidNameMap[] = { { UID_SegmentationStorage, "SegmentationStorage" }, { UID_SegmentedVolumeRenderingVolumetricPresentationStateStorage, "SegmentedVolumeRenderingVolumetricPresentationStateStorage" }, { UID_SimplifiedAdultEchoSRStorage, "SimplifiedAdultEchoSRStorage" }, + { UID_SleepElectroencephalogramWaveformStorage, "SleepElectroencephalogramWaveformStorage" }, { UID_SpatialFiducialsStorage, "SpatialFiducialsStorage" }, { UID_SpatialRegistrationStorage, "SpatialRegistrationStorage" }, { UID_SpectaclePrescriptionReportStorage, "SpectaclePrescriptionReportStorage" }, @@ -266,6 +283,8 @@ static const UIDNameMap uidNameMap[] = { { UID_SurfaceScanMeshStorage, "SurfaceScanMeshStorage" }, { UID_SurfaceScanPointCloudStorage, "SurfaceScanPointCloudStorage" }, { UID_SurfaceSegmentationStorage, "SurfaceSegmentationStorage" }, + { UID_TomotherapeuticRadiationRecordStorage, "TomotherapeuticRadiationRecordStorage" }, + { UID_TomotherapeuticRadiationStorage, "TomotherapeuticRadiationStorage" }, { UID_TractographyResultsStorage, "TractographyResultsStorage" }, { UID_TwelveLeadECGWaveformStorage, "TwelveLeadECGWaveformStorage" }, { UID_UltrasoundImageStorage, "UltrasoundImageStorage" }, @@ -353,6 +372,7 @@ static const UIDNameMap uidNameMap[] = { { UID_UnifiedProcedureStepWatchSOPClass, "UnifiedProcedureStepWatchSOPClass" }, { UID_UnifiedProcedureStepPullSOPClass, "UnifiedProcedureStepPullSOPClass" }, { UID_UnifiedProcedureStepEventSOPClass, "UnifiedProcedureStepEventSOPClass" }, + { UID_UnifiedProcedureStepQuerySOPClass, "UnifiedProcedureStepQuerySOPClass" }, { UID_UPSGlobalSubscriptionSOPInstance, "UPSGlobalSubscriptionSOPInstance" }, { UID_UPSFilteredGlobalSubscriptionSOPInstance, "UPSFilteredGlobalSubscriptionSOPInstance" }, @@ -459,6 +479,12 @@ static const UIDNameMap uidNameMap[] = { { UID_DisplaySystemSOPClass, "DisplaySystemSOPClass" }, { UID_DisplaySystemSOPInstance, "DisplaySystemSOPInstance" }, + // Real-Time Video + { UID_VideoEndoscopicImageRealTimeCommunication, "VideoEndoscopicImageRealTimeCommunication" }, + { UID_VideoPhotographicImageRealTimeCommunication, "VideoPhotographicImageRealTimeCommunication" }, + { UID_AudioWaveformRealTimeCommunication, "AudioWaveformRealTimeCommunication" }, + { UID_RenditionSelectionDocumentRealTimeCommunication, "RenditionSelectionDocumentRealTimeCommunication" }, + // Other { UID_RETIRED_BasicStudyContentNotificationSOPClass, "RETIRED_BasicStudyContentNotificationSOPClass" }, { UID_RETIRED_StudyComponentManagementSOPClass, "RETIRED_StudyComponentManagementSOPClass" }, @@ -533,7 +559,13 @@ static const UIDNameMap uidNameMap[] = { { UID_SPM2T2FrameOfReference, "SPM2T2FrameOfReference" }, { UID_SPM2TRANSMFrameOfReference, "SPM2TRANSMFrameOfReference" }, { UID_SPM2WHITEFrameOfReference, "SPM2WHITEFrameOfReference" }, + { UID_StandardRoboticCoordinateSystemFrameOfReference, "StandardRoboticCoordinateSystemFrameOfReference" }, { UID_TalairachBrainAtlasFrameOfReference, "TalairachBrainAtlasFrameOfReference" }, + { UID_SRI24FrameOfReference, "SRI24FrameOfReferenc" }, + { UID_Colin27FrameOfReference, "Colin27FrameOfReference" }, + { UID_LPBA40AIRFrameOfReference, "LPBA40AIRFrameOfReference" }, + { UID_LPBA40FLIRTFrameOfReference, "LPBA40FLIRTFrameOfReference" }, + { UID_LPBA40SPM5FrameOfReference, "LPBA40SPM5FrameOfReference" }, // UTC Synchronization Frame of Reference { UID_UniversalCoordinatedTimeSynchronizationFrameOfReference, "UniversalCoordinatedTimeSynchronizationFrameOfReference" }, @@ -589,10 +621,12 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_BasicTextSRStorage, UID_BasicVoiceAudioWaveformStorage, UID_BlendingSoftcopyPresentationStateStorage, + UID_BodyPositionWaveformStorage, UID_BreastProjectionXRayImageStorageForPresentation, UID_BreastProjectionXRayImageStorageForProcessing, UID_BreastTomosynthesisImageStorage, UID_CardiacElectrophysiologyWaveformStorage, + UID_CArmPhotonElectronRadiationRecordStorage, UID_CArmPhotonElectronRadiationStorage, UID_ChestCADSRStorage, UID_ColonCADSRStorage, @@ -606,13 +640,18 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_CTImageStorage, UID_CTPerformedProcedureProtocolStorage, UID_DeformableSpatialRegistrationStorage, + UID_DermoscopicPhotographyImageStorage, UID_DigitalIntraOralXRayImageStorageForPresentation, UID_DigitalIntraOralXRayImageStorageForProcessing, UID_DigitalMammographyXRayImageStorageForPresentation, UID_DigitalMammographyXRayImageStorageForProcessing, UID_DigitalXRayImageStorageForPresentation, UID_DigitalXRayImageStorageForProcessing, + UID_ElectromyogramWaveformStorage, + UID_ElectrooculogramWaveformStorage, UID_EncapsulatedCDAStorage, + UID_EncapsulatedMTLStorage, + UID_EncapsulatedOBJStorage, UID_EncapsulatedPDFStorage, UID_EncapsulatedSTLStorage, UID_EnhancedCTImageStorage, @@ -643,6 +682,7 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_MammographyCADSRStorage, UID_MRImageStorage, UID_MRSpectroscopyStorage, + UID_MultichannelRespiratoryWaveformStorage, UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, UID_MultiframeSingleBitSecondaryCaptureImageStorage, @@ -668,6 +708,9 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_RawDataStorage, UID_RealWorldValueMappingStorage, UID_RespiratoryWaveformStorage, + UID_RoboticArmRadiationStorage, + UID_RoboticRadiationRecordStorage, + UID_RoutineScalpElectroencephalogramWaveformStorage, UID_RTBeamsDeliveryInstructionStorage, UID_RTBeamsTreatmentRecordStorage, UID_RTBrachyApplicationSetupDeliveryInstructionStorage, @@ -678,6 +721,8 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_RTIonPlanStorage, UID_RTPhysicianIntentStorage, UID_RTPlanStorage, + UID_RTRadiationRecordSetStorage, + UID_RTRadiationSalvageRecordStorage, UID_RTRadiationSetStorage, UID_RTSegmentAnnotationStorage, UID_RTStructureSetStorage, @@ -686,6 +731,7 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_SegmentationStorage, UID_SegmentedVolumeRenderingVolumetricPresentationStateStorage, UID_SimplifiedAdultEchoSRStorage, + UID_SleepElectroencephalogramWaveformStorage, UID_SpatialFiducialsStorage, UID_SpatialRegistrationStorage, UID_SpectaclePrescriptionReportStorage, @@ -694,6 +740,8 @@ const char* dcmAllStorageSOPClassUIDs[] = { UID_SurfaceScanMeshStorage, UID_SurfaceScanPointCloudStorage, UID_SurfaceSegmentationStorage, + UID_TomotherapeuticRadiationRecordStorage, + UID_TomotherapeuticRadiationStorage, UID_TractographyResultsStorage, UID_TwelveLeadECGWaveformStorage, UID_UltrasoundImageStorage, @@ -892,16 +940,24 @@ const char* dcmLongSCUStorageSOPClassUIDs[] = { // recently approved // UID_AcquisitionContextSRStorage, // UID_AdvancedBlendingPresentationStateStorage, +// UID_BodyPositionWaveformStorage, // UID_BreastProjectionXRayImageStorageForPresentation, // UID_BreastProjectionXRayImageStorageForProcessing, +// UID_CArmPhotonElectronRadiationRecordStorage, // UID_CArmPhotonElectronRadiationStorage, // UID_CompositingPlanarMPRVolumetricPresentationStateStorage, // UID_ContentAssessmentResultsStorage, // UID_CornealTopographyMapStorage, // UID_CTPerformedProcedureProtocolStorage, +// UID_DermoscopicPhotographyImageStorage, +// UID_ElectromyogramWaveformStorage, +// UID_ElectrooculogramWaveformStorage, +// UID_EncapsulatedMTLStorage, +// UID_EncapsulatedOBJStorage, // UID_EncapsulatedSTLStorage, // UID_ExtensibleSRStorage, // UID_GrayscalePlanarMPRVolumetricPresentationStateStorage +// UID_MultichannelRespiratoryWaveformStorage, // UID_MultipleVolumeRenderingVolumetricPresentationStateStorage, // UID_OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage, // UID_OphthalmicOpticalCoherenceTomographyEnFaceImageStorage, @@ -910,12 +966,20 @@ const char* dcmLongSCUStorageSOPClassUIDs[] = { // UID_PerformedImagingAgentAdministrationSRStorage, // UID_PlannedImagingAgentAdministrationSRStorage, // UID_RadiopharmaceuticalRadiationDoseSRStorage, +// UID_RoboticArmRadiationStorage, +// UID_RoboticRadiationRecordStorage, +// UID_RoutineScalpElectroencephalogramWaveformStorage, // UID_RTBrachyApplicationSetupDeliveryInstructionStorage, // UID_RTPhysicianIntentStorage, +// UID_RTRadiationRecordSetStorage, +// UID_RTRadiationSalvageRecordStorage, // UID_RTRadiationSetStorage, // UID_RTSegmentAnnotationStorage, // UID_SegmentedVolumeRenderingVolumetricPresentationStateStorage, // UID_SimplifiedAdultEchoSRStorage, +// UID_SleepElectroencephalogramWaveformStorage, +// UID_TomotherapeuticRadiationRecordStorage, +// UID_TomotherapeuticRadiationStorage, // UID_TractographyResultsStorage, // UID_VolumeRenderingVolumetricPresentationStateStorage, // UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, @@ -1073,6 +1137,7 @@ const char* dcmImageSOPClassUIDs[] = { UID_ComputedRadiographyImageStorage, UID_CTImageStorage, UID_CornealTopographyMapStorage, + UID_DermoscopicPhotographyImageStorage, UID_DigitalIntraOralXRayImageStorageForPresentation, UID_DigitalIntraOralXRayImageStorageForProcessing, UID_DigitalMammographyXRayImageStorageForPresentation, @@ -1169,11 +1234,13 @@ static const DcmModalityTable modalities[] = { { UID_BasicTextSRStorage, "SRt", 4096 }, { UID_BasicVoiceAudioWaveformStorage, "AUV", 4096 }, { UID_BlendingSoftcopyPresentationStateStorage, "PSb", 4096 }, + { UID_BodyPositionWaveformStorage, "WVb", 4096 }, { UID_BreastProjectionXRayImageStorageForPresentation, "BX", 4096 * 4096 * 2 }, { UID_BreastProjectionXRayImageStorageForProcessing, "BP", 4096 * 4096 * 2 }, { UID_BreastTomosynthesisImageStorage, "BT", 4096 * 4096 * 2 }, { UID_CardiacElectrophysiologyWaveformStorage, "WVc", 4096 }, - { UID_CArmPhotonElectronRadiationStorage, "RRc", 4096 }, + { UID_CArmPhotonElectronRadiationRecordStorage, "RRc", 4096 }, + { UID_CArmPhotonElectronRadiationStorage, "Rca", 4096 }, { UID_ChestCADSRStorage, "SRh", 4096 }, { UID_ColonCADSRStorage, "SRo", 4096 }, { UID_ColorPaletteStorage, "CP", 4096 }, @@ -1188,13 +1255,18 @@ static const DcmModalityTable modalities[] = { { UID_CTImageStorage, "CT", 512 * 512 * 2 }, { UID_CTPerformedProcedureProtocolStorage, "PPp", 4096 }, { UID_DeformableSpatialRegistrationStorage, "RGd", 4096 }, + { UID_DermoscopicPhotographyImageStorage, "VLd", 768 * 576 * 3 }, { UID_DigitalIntraOralXRayImageStorageForPresentation, "DXo", 1024 * 1024 * 2 }, { UID_DigitalIntraOralXRayImageStorageForProcessing, "DPo", 1024 * 1024 * 2 }, { UID_DigitalMammographyXRayImageStorageForPresentation, "DXm", 4096 * 4096 * 2 }, { UID_DigitalMammographyXRayImageStorageForProcessing, "DPm", 4096 * 4096 * 2 }, { UID_DigitalXRayImageStorageForPresentation, "DX", 2048 * 2048 * 2 }, { UID_DigitalXRayImageStorageForProcessing, "DP", 2048 * 2048 * 2 }, + { UID_ElectromyogramWaveformStorage, "EMG", 4096 }, + { UID_ElectrooculogramWaveformStorage, "EOG", 4096 }, { UID_EncapsulatedCDAStorage, "CDA", 4096 }, + { UID_EncapsulatedMTLStorage, "MTL", 4096 }, + { UID_EncapsulatedOBJStorage, "OBJ", 4096 }, { UID_EncapsulatedPDFStorage, "PDF", 1024 * 1024 }, { UID_EncapsulatedSTLStorage, "STL", 4096 }, { UID_EnhancedCTImageStorage, "CTe", 256 * 512 * 512 }, @@ -1229,6 +1301,7 @@ static const DcmModalityTable modalities[] = { { UID_MammographyCADSRStorage, "SRm", 4096 }, { UID_MRImageStorage, "MR", 256 * 256 * 2 }, { UID_MRSpectroscopyStorage, "MRs", 256 * 512 * 512 }, + { UID_MultichannelRespiratoryWaveformStorage, "WVm", 4096 }, { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "SCb", 512 * 512 }, { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "SCw", 512 * 512 * 2 }, { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "SCs", 1024 * 1024 }, /* roughly an A4 300dpi scan */ @@ -1255,6 +1328,9 @@ static const DcmModalityTable modalities[] = { { UID_RawDataStorage, "RAW", 512 * 512 * 256 }, { UID_RealWorldValueMappingStorage, "RWM", 4096 }, { UID_RespiratoryWaveformStorage, "WVr", 4096 }, + { UID_RoboticArmRadiationStorage, "Rra", 4096 }, /* was RRr */ + { UID_RoboticRadiationRecordStorage, "RRr", 4096 }, + { UID_RoutineScalpElectroencephalogramWaveformStorage, "EEG", 4096 }, { UID_RTBeamsDeliveryInstructionStorage, "RTd", 4096 }, { UID_RTBeamsTreatmentRecordStorage, "RTb", 4096 }, { UID_RTBrachyApplicationSetupDeliveryInstructionStorage, "RTa", 4096 }, @@ -1265,14 +1341,17 @@ static const DcmModalityTable modalities[] = { { UID_RTIonPlanStorage, "RPi", 4096 }, { UID_RTPlanStorage, "RP" , 4096 }, { UID_RTPhysicianIntentStorage, "RIp", 4096 }, - { UID_RTRadiationSetStorage, "RRs", 4096 }, - { UID_RTSegmentAnnotationStorage, "RSa", 4096 }, + { UID_RTRadiationRecordSetStorage, "RSr", 4096 }, + { UID_RTRadiationSalvageRecordStorage, "RRs", 4096 }, + { UID_RTRadiationSetStorage, "RSe", 4096 }, /* was RRs */ + { UID_RTSegmentAnnotationStorage, "RAs", 4096 }, /* was RRs */ { UID_RTStructureSetStorage, "RS", 4096 }, { UID_RTTreatmentSummaryRecordStorage, "RTs", 4096 }, { UID_SecondaryCaptureImageStorage, "SC", 512 * 512 * 2 }, { UID_SegmentationStorage, "SG", 4096 }, { UID_SegmentedVolumeRenderingVolumetricPresentationStateStorage, "VPs", 4096 }, { UID_SimplifiedAdultEchoSRStorage, "SRu", 4096 }, + { UID_SleepElectroencephalogramWaveformStorage, "WVs", 4096 }, { UID_SpatialFiducialsStorage, "FID", 4096 }, { UID_SpatialRegistrationStorage, "RGs", 4096 }, { UID_SpectaclePrescriptionReportStorage, "SRs", 4096 }, @@ -1281,6 +1360,8 @@ static const DcmModalityTable modalities[] = { { UID_SurfaceScanMeshStorage, "SSm", 4096 }, { UID_SurfaceScanPointCloudStorage, "SSp", 4096 }, { UID_SurfaceSegmentationStorage, "SGs", 4096 }, + { UID_TomotherapeuticRadiationRecordStorage, "RRt", 4096 }, + { UID_TomotherapeuticRadiationStorage, "Rto", 4096 }, /* was RRt */ { UID_TractographyResultsStorage, "TR", 4096 }, { UID_TwelveLeadECGWaveformStorage, "TLE", 4096 }, { UID_UltrasoundImageStorage, "US", 512 * 512 }, @@ -1591,14 +1672,14 @@ static long gethostid(void) /* get volume information of the system drive */ char systemDrive[MAX_PATH]; DWORD serialNumber = 0; - if (GetSystemDirectory(systemDrive, OFstatic_cast(UINT, sizeof(systemDrive))) >= 0) + if (GetSystemDirectoryA(systemDrive, OFstatic_cast(UINT, sizeof(systemDrive))) >= 0) { /* check for proper pathname */ if ((strlen(systemDrive) >= 3) && (systemDrive[1] == ':') && (systemDrive[2] == '\\')) { /* truncate the pathname directly after the drive specification */ systemDrive[3] = 0; - if (!GetVolumeInformation(systemDrive, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) + if (!GetVolumeInformationA(systemDrive, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) serialNumber = 0; } } diff --git a/dcmdata/libsrc/dcvr.cc b/dcmdata/libsrc/dcvr.cc index f27c9343..85398553 100644 --- a/dcmdata/libsrc/dcvr.cc +++ b/dcmdata/libsrc/dcvr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -138,7 +138,8 @@ static const DcmVREntry DcmVRDict[] = { { EVR_US, "US", &noDelimiters, sizeof(Uint16), DCMVR_PROP_NONE, 2, 2 }, { EVR_UT, "UT", &noDelimiters, sizeof(char), DCMVR_PROP_ISASTRING | DCMVR_PROP_EXTENDEDLENGTHENCODING | DCMVR_PROP_ISAFFECTEDBYCHARSET, 0, 4294967294U }, { EVR_UV, "UV", &noDelimiters, sizeof(Uint64), DCMVR_PROP_EXTENDEDLENGTHENCODING, 8, 8 }, - { EVR_ox, "ox", &noDelimiters, sizeof(Uint8), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, 4294967294U }, + { EVR_ox, "ox", &noDelimiters, sizeof(Uint8), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING | DCMVR_PROP_UNDEFINEDLENGTH, 0, 4294967294U }, + { EVR_px, "px", &noDelimiters, sizeof(Uint8), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING | DCMVR_PROP_UNDEFINEDLENGTH, 0, 4294967294U }, { EVR_xs, "xs", &noDelimiters, sizeof(Uint16), DCMVR_PROP_NONSTANDARD, 2, 2 }, { EVR_lt, "lt", &noDelimiters, sizeof(Uint16), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, 4294967294U }, { EVR_na, "na", &noDelimiters, 0, DCMVR_PROP_NONSTANDARD, 0, 0 }, @@ -283,6 +284,7 @@ DcmVR::getValidEVR() const evr = EVR_OW; break; case EVR_ox: + case EVR_px: case EVR_pixelSQ: evr = EVR_OB; break; @@ -477,16 +479,17 @@ DcmVR::isEquivalent(const DcmVR& avr) const switch (vr) { case EVR_ox: + case EVR_px: result = (evr == EVR_OB || evr == EVR_OW); break; case EVR_lt: result = (evr == EVR_OW || evr == EVR_US || evr == EVR_SS); break; case EVR_OB: - result = (evr == EVR_ox); + result = (evr == EVR_ox || evr == EVR_px); break; case EVR_OW: - result = (evr == EVR_ox || evr == EVR_lt); + result = (evr == EVR_ox || evr == EVR_px || evr == EVR_lt); break; case EVR_up: result = (evr == EVR_UL); diff --git a/dcmdata/libsrc/dcvrat.cc b/dcmdata/libsrc/dcvrat.cc index 428f9a59..8d94594d 100644 --- a/dcmdata/libsrc/dcvrat.cc +++ b/dcmdata/libsrc/dcvrat.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -260,31 +260,36 @@ OFCondition DcmAttributeTag::writeJson(STD_NAMESPACE ostream &out, { // always write JSON Opener DcmElement::writeJsonOpener(out, format); - Uint16 *uintVals; - getUint16Array(uintVals); - const unsigned long vm = getVM(); - // check for empty/invalid value - if ((uintVals != NULL) && (vm > 0)) + + if (!isEmpty()) { - format.printValuePrefix(out); - out << STD_NAMESPACE uppercase << STD_NAMESPACE setfill('0'); - // print tag values "ggggeeee" in hex mode (upper case!) - out << "\""; - out << STD_NAMESPACE hex << STD_NAMESPACE setw(4) << (*(uintVals++)); - out << STD_NAMESPACE setw(4) << (*(uintVals++)) << STD_NAMESPACE dec; - out << "\""; - for (unsigned long valNo = 1; valNo < vm; valNo++) + Uint16 *uintVals; + getUint16Array(uintVals); + const unsigned long vm = getVM(); + // check for empty/invalid value + if ((uintVals != NULL) && (vm > 0)) { - format.printNextArrayElementPrefix(out); + format.printValuePrefix(out); + out << STD_NAMESPACE uppercase << STD_NAMESPACE setfill('0'); + // print tag values "ggggeeee" in hex mode (upper case!) out << "\""; out << STD_NAMESPACE hex << STD_NAMESPACE setw(4) << (*(uintVals++)); out << STD_NAMESPACE setw(4) << (*(uintVals++)) << STD_NAMESPACE dec; out << "\""; + for (unsigned long valNo = 1; valNo < vm; valNo++) + { + format.printNextArrayElementPrefix(out); + out << "\""; + out << STD_NAMESPACE hex << STD_NAMESPACE setw(4) << (*(uintVals++)); + out << STD_NAMESPACE setw(4) << (*(uintVals++)) << STD_NAMESPACE dec; + out << "\""; + } + // reset i/o manipulators + out << STD_NAMESPACE nouppercase << STD_NAMESPACE setfill(' '); + format.printValueSuffix(out); } - // reset i/o manipulators - out << STD_NAMESPACE nouppercase << STD_NAMESPACE setfill(' '); - format.printValueSuffix(out); } + // write normal JSON closer DcmElement::writeJsonCloser(out, format); // always report success diff --git a/dcmdata/libsrc/dcvrds.cc b/dcmdata/libsrc/dcvrds.cc index e8895e76..0cf8d7da 100644 --- a/dcmdata/libsrc/dcvrds.cc +++ b/dcmdata/libsrc/dcvrds.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2016, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -114,6 +114,9 @@ OFCondition DcmDecimalString::getFloat64(Float64 &doubleVal, } +// ******************************** + + OFCondition DcmDecimalString::getFloat64Vector(OFVector &doubleVals) { /* get stored value */ @@ -162,6 +165,7 @@ OFCondition DcmDecimalString::getFloat64Vector(OFVector &doubleVals) } + // ******************************** @@ -181,6 +185,58 @@ OFCondition DcmDecimalString::getOFString(OFString &stringVal, // ******************************** +OFCondition DcmDecimalString::putFloat64(const Float64 val, + const unsigned long pos) +{ + return putFloat64Prec(val, pos, 6); +} + + +OFCondition DcmDecimalString::putFloat64Prec(const Float64 val, + const unsigned long pos, + const Uint8 prec, + const OFBool cutTrailZeroes) +{ + if (prec > 100) + return EC_IllegalParameter; + + // Reserve enough bytes for conversion (considering high precision values that + // might be cut off later, i.e. 16 for integer part, 1 for dot, 14 max precision, 1 for NUL, i.e. + char buf[16 + 1 + 14 +1]; + int written = OFStandard::snprintf(buf, 32, "%.*f", prec, val); + if (written > 31 /* NUL not counting in */) + { + return EC_IllegalParameter; + } + + OFString str(buf); + if (cutTrailZeroes) + { + size_t dot = str.find_last_of('.'); + if (dot != OFString_npos) + { + size_t last_valid = str.find_last_not_of('0'); + if (last_valid != str.length() -1) + { + if (str[last_valid] == '.') + str = str.substr(0, last_valid); + else + str = str.substr(0, last_valid+1); + } + } + } + if (str.length() > 16) + { + return EC_IllegalParameter; + } + + return putOFStringAtPos(str.c_str(), pos); +} + + +// ******************************** + + OFCondition DcmDecimalString::writeXML(STD_NAMESPACE ostream &out, const size_t flags) { @@ -226,9 +282,10 @@ OFCondition DcmDecimalString::writeJson(STD_NAMESPACE ostream &out, { /* always write JSON Opener */ writeJsonOpener(out, format); - /* write element value (if loaded) */ - if (valueLoaded()) + + if (!isEmpty()) { + /* write element value */ OFString bulkDataValue; if (format.asBulkDataURI(getTag(), bulkDataValue)) { @@ -237,32 +294,37 @@ OFCondition DcmDecimalString::writeJson(STD_NAMESPACE ostream &out, } else { - /* get string data (without normalization) */ - char *value_ = OFnullptr; - Uint32 length = 0; - getString(value_, length); - if ((value_ != OFnullptr) && (length > 0)) + const unsigned long vm = getVM(); + if (vm > 0) { - /* explicitly convert to OFString because of possible NULL bytes */ - OFString value(value_, length); + OFString value; + OFString vmstring = "1"; OFCondition status = getOFString(value, 0L); if (status.bad()) return status; format.printValuePrefix(out); - DcmJsonFormat::printNumberDecimal(out, value); - const unsigned long vm = getVM(); + // if the value is a proper number, write as JSON number, + // otherwise write as JSON string. + if (checkStringValue(value, vmstring).good()) + DcmJsonFormat::printNumberDecimal(out, value); + else DcmJsonFormat::printValueString(out, value); for (unsigned long valNo = 1; valNo < vm; ++valNo) { status = getOFString(value, valNo); if (status.bad()) return status; format.printNextArrayElementPrefix(out); - DcmJsonFormat::printNumberDecimal(out, value); + // if the value is a proper number, write as JSON number, + // otherwise write as JSON string. + if (checkStringValue(value, vmstring).good()) + DcmJsonFormat::printNumberDecimal(out, value); + else DcmJsonFormat::printValueString(out, value); } format.printValueSuffix(out); } } } + /* write JSON Closer */ writeJsonCloser(out, format); /* always report success */ diff --git a/dcmdata/libsrc/dcvrfd.cc b/dcmdata/libsrc/dcvrfd.cc index acf6758c..72d9dd5f 100644 --- a/dcmdata/libsrc/dcvrfd.cc +++ b/dcmdata/libsrc/dcvrfd.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -21,9 +21,11 @@ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrfd.h" #include "dcmtk/ofstd/ofstream.h" #include "dcmtk/ofstd/ofstd.h" -#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/ofstd/ofmath.h" +#include "dcmtk/dcmdata/dcjson.h" #define INCLUDE_CSTDIO #define INCLUDE_CSTRING @@ -395,3 +397,57 @@ OFBool DcmFloatingPointDouble::matches(const DcmElement& candidate, } return OFFalse; } + +// ******************************** + +OFCondition DcmFloatingPointDouble::writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format) +{ + /* always write JSON Opener */ + writeJsonOpener(out, format); + /* write element value (if non-empty) */ + if (!isEmpty()) + { + OFCondition status; + const unsigned long vm = getVM(); + + if (! format.getJsonExtensionEnabled()) + { + // check if any values is 'inf' or 'nan', and return an error in this case + // since the JSON extension that would allow us to write these is not enabled + Float64 f = 0.0; + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getFloat64(f, valNo); + if (status.bad()) return status; + if ((OFMath::isinf)(f) || (OFMath::isnan)(f)) return EC_CannotWriteJsonNumber; + } + } + + OFString value; + if (format.asBulkDataURI(getTag(), value)) + { + format.printBulkDataURIPrefix(out); + DcmJsonFormat::printString(out, value); + } + else + { + status = getOFString(value, 0L); + if (status.bad()) return status; + format.printValuePrefix(out); + DcmJsonFormat::printNumberDecimal(out, value); + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getOFString(value, valNo); + if (status.bad()) return status; + format.printNextArrayElementPrefix(out); + DcmJsonFormat::printNumberDecimal(out, value); + } + format.printValueSuffix(out); + } + } + /* write JSON Closer */ + writeJsonCloser(out, format); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvrfl.cc b/dcmdata/libsrc/dcvrfl.cc index c8673e69..5eb83faf 100644 --- a/dcmdata/libsrc/dcvrfl.cc +++ b/dcmdata/libsrc/dcvrfl.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -21,9 +21,11 @@ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrfl.h" #include "dcmtk/ofstd/ofstream.h" #include "dcmtk/ofstd/ofstd.h" -#include "dcmtk/dcmdata/dcvrfl.h" +#include "dcmtk/ofstd/ofmath.h" +#include "dcmtk/dcmdata/dcjson.h" #define INCLUDE_CSTDIO #define INCLUDE_CSTRING @@ -397,3 +399,57 @@ OFBool DcmFloatingPointSingle::matches(const DcmElement& candidate, } return OFFalse; } + +// ******************************** + +OFCondition DcmFloatingPointSingle::writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format) +{ + /* always write JSON Opener */ + writeJsonOpener(out, format); + /* write element value (if non-empty) */ + if (!isEmpty()) + { + OFCondition status; + const unsigned long vm = getVM(); + + if (! format.getJsonExtensionEnabled()) + { + // check if any values is 'inf' or 'nan', and return an error in this case + // since the JSON extension that would allow us to write these is not enabled + Float32 f = 0.0; + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getFloat32(f, valNo); + if (status.bad()) return status; + if ((OFMath::isinf)(f) || (OFMath::isnan)(f)) return EC_CannotWriteJsonNumber; + } + } + + OFString value; + if (format.asBulkDataURI(getTag(), value)) + { + format.printBulkDataURIPrefix(out); + DcmJsonFormat::printString(out, value); + } + else + { + status = getOFString(value, 0L); + if (status.bad()) return status; + format.printValuePrefix(out); + DcmJsonFormat::printNumberDecimal(out, value); + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getOFString(value, valNo); + if (status.bad()) return status; + format.printNextArrayElementPrefix(out); + DcmJsonFormat::printNumberDecimal(out, value); + } + format.printValueSuffix(out); + } + } + /* write JSON Closer */ + writeJsonCloser(out, format); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvris.cc b/dcmdata/libsrc/dcvris.cc index 876bbe3d..31c09318 100644 --- a/dcmdata/libsrc/dcvris.cc +++ b/dcmdata/libsrc/dcvris.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -154,9 +154,10 @@ OFCondition DcmIntegerString::writeJson(STD_NAMESPACE ostream &out, { /* always write JSON Opener */ writeJsonOpener(out, format); - /* write element value (if loaded) */ - if (valueLoaded()) + + if (!isEmpty()) { + /* write element value */ OFString bulkDataValue; if (format.asBulkDataURI(getTag(), bulkDataValue)) { @@ -165,32 +166,37 @@ OFCondition DcmIntegerString::writeJson(STD_NAMESPACE ostream &out, } else { - /* get string data (without normalization) */ - char *value_ = NULL; - Uint32 length = 0; - getString(value_, length); - if ((value_ != NULL) && (length > 0)) + const unsigned long vm = getVM(); + if (vm > 0) { - /* explicitly convert to OFString because of possible NULL bytes */ - OFString value(value_, length); + OFString value; + OFString vmstring = "1"; OFCondition status = getOFString(value, 0L); if (status.bad()) return status; format.printValuePrefix(out); - DcmJsonFormat::printNumberInteger(out, value); - const unsigned long vm = getVM(); + // if the value is a proper number, write as JSON number, + // otherwise write as JSON string. + if (checkStringValue(value, vmstring).good()) + DcmJsonFormat::printNumberInteger(out, value); + else DcmJsonFormat::printValueString(out, value); for (unsigned long valNo = 1; valNo < vm; ++valNo) { status = getOFString(value, valNo); if (status.bad()) return status; format.printNextArrayElementPrefix(out); - DcmJsonFormat::printNumberInteger(out, value); + // if the value is a proper number, write as JSON number, + // otherwise write as JSON string. + if (checkStringValue(value, vmstring).good()) + DcmJsonFormat::printNumberInteger(out, value); + else DcmJsonFormat::printValueString(out, value); } format.printValueSuffix(out); } } } + /* write JSON Closer */ writeJsonCloser(out, format); /* always report success */ diff --git a/dcmdata/libsrc/dcvrobow.cc b/dcmdata/libsrc/dcvrobow.cc index 6ad14ae4..e6c3ddb2 100644 --- a/dcmdata/libsrc/dcvrobow.cc +++ b/dcmdata/libsrc/dcvrobow.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -869,7 +869,8 @@ OFCondition DcmOtherByteOtherWord::writeJson(STD_NAMESPACE ostream &out, /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; - Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } diff --git a/dcmdata/libsrc/dcvrod.cc b/dcmdata/libsrc/dcvrod.cc index 1d63ccd8..b657ffdb 100644 --- a/dcmdata/libsrc/dcvrod.cc +++ b/dcmdata/libsrc/dcvrod.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2013-2019, OFFIS e.V. + * Copyright (C) 2013-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -180,7 +180,8 @@ OFCondition DcmOtherDouble::writeJson(STD_NAMESPACE ostream &out, /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; - Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } diff --git a/dcmdata/libsrc/dcvrof.cc b/dcmdata/libsrc/dcvrof.cc index 8c4e2355..2661b0bc 100644 --- a/dcmdata/libsrc/dcvrof.cc +++ b/dcmdata/libsrc/dcvrof.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2019, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -180,7 +180,8 @@ OFCondition DcmOtherFloat::writeJson(STD_NAMESPACE ostream &out, /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; - Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } diff --git a/dcmdata/libsrc/dcvrol.cc b/dcmdata/libsrc/dcvrol.cc index cbb1b6c6..5a0a3798 100644 --- a/dcmdata/libsrc/dcvrol.cc +++ b/dcmdata/libsrc/dcvrol.cc @@ -182,7 +182,8 @@ OFCondition DcmOtherLong::writeJson(STD_NAMESPACE ostream &out, /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; - Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } diff --git a/dcmdata/libsrc/dcvrov.cc b/dcmdata/libsrc/dcvrov.cc index c671732d..59d14566 100644 --- a/dcmdata/libsrc/dcvrov.cc +++ b/dcmdata/libsrc/dcvrov.cc @@ -182,7 +182,8 @@ OFCondition DcmOther64bitVeryLong::writeJson(STD_NAMESPACE ostream &out, /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; - Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* adjust byte order to little endian */ + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } diff --git a/dcmdata/libsrc/dcvrpn.cc b/dcmdata/libsrc/dcvrpn.cc index 3424ccc6..4654d4a8 100644 --- a/dcmdata/libsrc/dcvrpn.cc +++ b/dcmdata/libsrc/dcvrpn.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2017, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,6 +24,7 @@ #include "dcmtk/dcmdata/dcjson.h" #include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/ofstd/ofstd.h" // ******************************** @@ -117,7 +118,9 @@ OFCondition DcmPersonName::writeXML(STD_NAMESPACE ostream &out, /* PN requires special handling in the Native DICOM Model format */ if (flags & DCMTypes::XF_useNativeModel) { - /* write normal XML start tag */ + const OFBool convertNonASCII = (flags & DCMTypes::XF_convertNonASCII) > 0; + + /* write normal XML start tag */ DcmElement::writeXMLStartTag(out, flags); /* if the value is empty, we do not need to insert any PersonName attribute at all */ if (!isEmpty()) @@ -159,7 +162,14 @@ OFCondition DcmPersonName::writeXML(STD_NAMESPACE ostream &out, if (!components[c].empty()) { /* output name component, e.g. Onken */ - out << "<" << compNames[c] << ">" << components[c] << "" << OFendl; + out << "<" << compNames[c] << ">"; + + /* check whether conversion to XML markup string is required */ + if (OFStandard::checkForMarkupConversion(components[c], convertNonASCII)) + OFStandard::convertToMarkupStream(out, components[c], convertNonASCII); + else + out << components[c]; + out << "" << OFendl; } } out << "" << OFendl; // e.g. @@ -325,7 +335,8 @@ OFCondition DcmPersonName::writeJson(STD_NAMESPACE ostream &out, const char* componentEnd = it - 1; while (*componentEnd == ' ') --componentEnd; - out.write(begin, componentEnd - begin + 1); + OFString s(begin, 0, componentEnd - begin + 1); + DcmJsonFormat::escapeControlCharacters(out, s); } // writes the name of the current component group and all components diff --git a/dcmdata/libsrc/dcvrpobw.cc b/dcmdata/libsrc/dcvrpobw.cc index 67df5ee2..fac45489 100644 --- a/dcmdata/libsrc/dcvrpobw.cc +++ b/dcmdata/libsrc/dcvrpobw.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2019, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -32,7 +32,8 @@ DcmPolymorphOBOW::DcmPolymorphOBOW( changeVR(OFFalse), currentVR(EVR_OW) { - if (getTag().getEVR() == EVR_ox || getTag().getEVR() == EVR_lt) setTagVR(EVR_OW); + if (getTag().getEVR() == EVR_ox || getTag().getEVR() == EVR_px || getTag().getEVR() == EVR_lt) + setTagVR(EVR_OW); } DcmPolymorphOBOW::DcmPolymorphOBOW(const DcmPolymorphOBOW & oldObj) diff --git a/dcmdata/libsrc/dcvrsv.cc b/dcmdata/libsrc/dcvrsv.cc index 6360a570..3695880e 100644 --- a/dcmdata/libsrc/dcvrsv.cc +++ b/dcmdata/libsrc/dcvrsv.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -21,9 +21,10 @@ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrsv.h" #include "dcmtk/ofstd/ofstream.h" -#include "dcmtk/dcmdata/dcvrsv.h" +#include "dcmtk/dcmdata/dcjson.h" #define INCLUDE_CSTDIO #define INCLUDE_CSTRING @@ -394,3 +395,65 @@ OFCondition DcmSigned64bitVeryLong::verify(const OFBool autocorrect) errorFlag = EC_Normal; return errorFlag; } + +// ******************************** + +// The largest and smallest number permitted in Javascript +#define JSON_MAX_SAFE_INTEGER 9007199254740991ll +#define JSON_MIN_SAFE_INTEGER -9007199254740991ll + +OFCondition DcmSigned64bitVeryLong::writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format) +{ + /* always write JSON Opener */ + writeJsonOpener(out, format); + + if (!isEmpty()) + { + + /* write element value */ + OFString bulkDataValue; + if (format.asBulkDataURI(getTag(), bulkDataValue)) + { + format.printBulkDataURIPrefix(out); + DcmJsonFormat::printString(out, bulkDataValue); + } + else + { + const unsigned long vm = getVM(); + OFString value; + Sint64 v = 0; + + OFCondition status = getOFString(value, 0L); + if (status.bad()) return status; + format.printValuePrefix(out); + + // check if we can represent the value as a JSON number. + // JSON numbers should be in the interval [JSON_MAX_SAFE_INTEGER..JSON_MAX_SAFE_INTEGER]. + status = getSint64(v, 0L); + if (status.bad() || (v > JSON_MAX_SAFE_INTEGER) || (v < JSON_MIN_SAFE_INTEGER)) + DcmJsonFormat::printValueString(out, value); + else DcmJsonFormat::printNumberInteger(out, value); + + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getOFString(value, valNo); + if (status.bad()) return status; + format.printNextArrayElementPrefix(out); + + // check if we can represent the value as a JSON number. + // JSON numbers should be in the interval [JSON_MAX_SAFE_INTEGER..JSON_MAX_SAFE_INTEGER]. + status = getSint64(v, valNo); + if (status.bad() || (v > JSON_MAX_SAFE_INTEGER) || (v < JSON_MIN_SAFE_INTEGER)) + DcmJsonFormat::printValueString(out, value); + else DcmJsonFormat::printNumberInteger(out, value); + } + format.printValueSuffix(out); + } + } + + /* write JSON Closer */ + writeJsonCloser(out, format); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvruv.cc b/dcmdata/libsrc/dcvruv.cc index 501a2902..de693660 100644 --- a/dcmdata/libsrc/dcvruv.cc +++ b/dcmdata/libsrc/dcvruv.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -21,9 +21,10 @@ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvruv.h" #include "dcmtk/ofstd/ofstream.h" -#include "dcmtk/dcmdata/dcvruv.h" +#include "dcmtk/dcmdata/dcjson.h" #define INCLUDE_CSTDIO #define INCLUDE_CSTRING @@ -393,3 +394,65 @@ OFCondition DcmUnsigned64bitVeryLong::verify(const OFBool autocorrect) errorFlag = EC_Normal; return errorFlag; } + + +// ******************************** + +// The largest number permitted in Javascript +#define JSON_MAX_SAFE_INTEGER 9007199254740991ull + +OFCondition DcmUnsigned64bitVeryLong::writeJson(STD_NAMESPACE ostream &out, + DcmJsonFormat &format) +{ + /* always write JSON Opener */ + writeJsonOpener(out, format); + + if (!isEmpty()) + { + + /* write element value */ + OFString bulkDataValue; + if (format.asBulkDataURI(getTag(), bulkDataValue)) + { + format.printBulkDataURIPrefix(out); + DcmJsonFormat::printString(out, bulkDataValue); + } + else + { + const unsigned long vm = getVM(); + OFString value; + Uint64 v = 0; + + OFCondition status = getOFString(value, 0L); + if (status.bad()) return status; + format.printValuePrefix(out); + + // check if we can represent the value as a JSON number. + // Unsigned JSON numbers should be <= JSON_MAX_SAFE_INTEGER. + status = getUint64(v, 0L); + if (status.bad() || (v > JSON_MAX_SAFE_INTEGER)) + DcmJsonFormat::printValueString(out, value); + else DcmJsonFormat::printNumberInteger(out, value); + + for (unsigned long valNo = 1; valNo < vm; ++valNo) + { + status = getOFString(value, valNo); + if (status.bad()) return status; + format.printNextArrayElementPrefix(out); + + // check if we can represent the value as a JSON number. + // Unsigned JSON numbers should be <= JSON_MAX_SAFE_INTEGER. + status = getUint64(v, valNo); + if (status.bad() || (v > JSON_MAX_SAFE_INTEGER)) + DcmJsonFormat::printValueString(out, value); + else DcmJsonFormat::printNumberInteger(out, value); + } + format.printValueSuffix(out); + } + } + + /* write JSON Closer */ + writeJsonCloser(out, format); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/tests/CMakeLists.txt b/dcmdata/tests/CMakeLists.txt index c1a1c6c4..8e2d79d2 100644 --- a/dcmdata/tests/CMakeLists.txt +++ b/dcmdata/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # declare executables -DCMTK_ADD_EXECUTABLE(dcmdata_tests tests tpread ti2dbmp tchval tpath tvrdatim telemlen tparser tdict tvrds tvrfd tvrpn tvrui tvrol tvrov tvrsv tvruv tstrval tspchrs tparent tfilter tvrcomp tmatch tnewdcme tgenuid) +DCMTK_ADD_EXECUTABLE(dcmdata_tests tests tpread ti2dbmp tchval tpath tvrdatim telemlen tparser tdict tvrds tvrfd tvrpn tvrui tvrol tvrov tvrsv tvruv tstrval tspchrs tparent tfilter tvrcomp tmatch tnewdcme tgenuid tsequen) # make sure executables are linked to the corresponding libraries DCMTK_TARGET_LINK_MODULES(dcmdata_tests i2d dcmdata oflog ofstd) diff --git a/dcmdata/tests/Makefile.dep b/dcmdata/tests/Makefile.dep index 6f141c65..25fd91d9 100644 --- a/dcmdata/tests/Makefile.dep +++ b/dcmdata/tests/Makefile.dep @@ -897,6 +897,65 @@ tpread.o: tpread.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \ ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcostrmz.h \ ../include/dcmtk/dcmdata/dcistrmz.h ../include/dcmtk/dcmdata/dcfcache.h +tsequen.o: tsequen.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcdeftag.h tspchrs.o: tspchrs.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ @@ -1197,7 +1256,8 @@ tvrds.o: tvrds.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ - ../include/dcmtk/dcmdata/dcdeftag.h + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h tvrfd.o: tvrfd.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ diff --git a/dcmdata/tests/Makefile.in b/dcmdata/tests/Makefile.in index eb003974..a2f44a66 100644 --- a/dcmdata/tests/Makefile.in +++ b/dcmdata/tests/Makefile.in @@ -24,7 +24,7 @@ I2DLIBS = -li2d objs = tests.o tpread.o ti2dbmp.o tchval.o tpath.o tvrdatim.o telemlen.o tparser.o \ tdict.o tvrds.o tvrfd.o tvrui.o tvrol.o tvrov.o tvrsv.o tvruv.o tstrval.o \ tspchrs.o tvrpn.o tparent.o tfilter.o tvrcomp.o tmatch.o tnewdcme.o \ - tgenuid.o + tgenuid.o tsequen.o progs = tests diff --git a/dcmdata/tests/tdict.cc b/dcmdata/tests/tdict.cc index 13e690d0..af8d6442 100644 --- a/dcmdata/tests/tdict.cc +++ b/dcmdata/tests/tdict.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2018, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -31,7 +31,8 @@ OFTEST(dcmdata_readingDataDictionary) { // Does loading the global data dictionary work? - OFCHECK(dcmDataDict.isDictionaryLoaded()); + if (!dcmDataDict.isDictionaryLoaded()) + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); } OFTEST(dcmdata_usingDataDictionary) diff --git a/dcmdata/tests/telemlen.cc b/dcmdata/tests/telemlen.cc index d275eff8..be26d11c 100644 --- a/dcmdata/tests/telemlen.cc +++ b/dcmdata/tests/telemlen.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2019, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -121,6 +121,7 @@ TEST_VR(EVR_UC) TEST_VR(EVR_UR) TEST_VR(EVR_UT) TEST_VR(EVR_ox) +TEST_VR(EVR_px) TEST_VR(EVR_lt) TEST_VR(EVR_UNKNOWN) TEST_VR(EVR_UN) diff --git a/dcmdata/tests/tests.cc b/dcmdata/tests/tests.cc index f6cb826e..9d5db2c0 100644 --- a/dcmdata/tests/tests.cc +++ b/dcmdata/tests/tests.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2019 OFFIS e.V. + * Copyright (C) 2011-2020 OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -34,6 +34,7 @@ OFTEST_REGISTER(dcmdata_decimalString_1); OFTEST_REGISTER(dcmdata_decimalString_2); OFTEST_REGISTER(dcmdata_decimalString_3); OFTEST_REGISTER(dcmdata_decimalString_4); +OFTEST_REGISTER(dcmdata_decimalString_putFloat64); OFTEST_REGISTER(dcmdata_floatingPointDouble); OFTEST_REGISTER(dcmdata_personName); OFTEST_REGISTER(dcmdata_uniqueIdentifier_1); @@ -84,11 +85,15 @@ OFTEST_REGISTER(dcmdata_elementLength_EVR_UT); OFTEST_REGISTER(dcmdata_elementLength_EVR_lt); OFTEST_REGISTER(dcmdata_elementLength_EVR_na); OFTEST_REGISTER(dcmdata_elementLength_EVR_ox); +OFTEST_REGISTER(dcmdata_elementLength_EVR_px); OFTEST_REGISTER(dcmdata_elementLength_EVR_up); OFTEST_REGISTER(dcmdata_elementLength_EVR_xs); OFTEST_REGISTER(dcmdata_elementLength_pixelItem); OFTEST_REGISTER(dcmdata_elementLength_pixelSequence); OFTEST_REGISTER(dcmdata_elementParent); +OFTEST_REGISTER(dcmdata_sequenceInsert); +OFTEST_REGISTER(dcmdata_pixelSequenceInsert); +OFTEST_REGISTER(dcmdata_findAndGetSequenceItem); OFTEST_REGISTER(dcmdata_parser_missingDelimitationItems); OFTEST_REGISTER(dcmdata_parser_missingSequenceDelimitationItem_1); OFTEST_REGISTER(dcmdata_parser_missingSequenceDelimitationItem_2); diff --git a/dcmdata/tests/tfilter.cc b/dcmdata/tests/tfilter.cc index 9370f302..b1cbbea4 100644 --- a/dcmdata/tests/tfilter.cc +++ b/dcmdata/tests/tfilter.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2012, OFFIS e.V. + * Copyright (C) 2012-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,10 +27,18 @@ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcfilter.h" +#include "dcmtk/dcmdata/dcdict.h" OFTEST( dcmdata_attribute_filter ) { + // make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + DcmAttributeFilter ct_filter( DCM_SOPClassUID, UID_CTImageStorage ); DcmItem item; @@ -45,9 +53,9 @@ OFTEST( dcmdata_attribute_filter ) // test iterator (array) based range const char* filter_range[3] = { - UID_ComputedRadiographyImageStorage, - UID_CTImageStorage, - UID_MRImageStorage + UID_ComputedRadiographyImageStorage, + UID_CTImageStorage, + UID_MRImageStorage }; // create filter from range (iterators) diff --git a/dcmdata/tests/tparser.cc b/dcmdata/tests/tparser.cc index cb8f93c3..e77214d6 100644 --- a/dcmdata/tests/tparser.cc +++ b/dcmdata/tests/tparser.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2018, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -437,26 +437,61 @@ static void testExplicitVRinDataset(OFBool useDictionaryVR, OFBool useDictionary OFTEST(dcmdata_parser_wrongExplicitVRinDataset_default) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + testExplicitVRinDataset(OFFalse, OFFalse); } OFTEST(dcmdata_parser_wrongExplicitVRinDataset_defaultVR_dictLen) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + testExplicitVRinDataset(OFFalse, OFTrue); } OFTEST(dcmdata_parser_wrongExplicitVRinDataset_dictVR_defaultLen) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + testExplicitVRinDataset(OFTrue, OFFalse); } OFTEST(dcmdata_parser_wrongExplicitVRinDataset_preferDataDict) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + testExplicitVRinDataset(OFTrue, OFTrue); } OFTEST(dcmdata_parser_undefinedLengthUNSequence) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + const Uint8 data[] = { // Sequence with undefined length and VR UN => gets read as implicit TS TAG_AND_LENGTH(DCM_IconImageSequence, 'U', 'N', UNDEFINED_LENGTH), diff --git a/dcmdata/tests/tpath.cc b/dcmdata/tests/tpath.cc index 5b18a928..0ad8f2e6 100644 --- a/dcmdata/tests/tpath.cc +++ b/dcmdata/tests/tpath.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2008-2017, OFFIS e.V. + * Copyright (C) 2008-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -152,7 +152,6 @@ static OFCondition testPathInsertionsWithWildcard(const OFString& path, OFTEST(dcmdata_pathAccess) { - /* make sure data dictionary is loaded */ if (!dcmDataDict.isDictionaryLoaded()) { diff --git a/dcmdata/tests/tpread.cc b/dcmdata/tests/tpread.cc index 52c4270a..2f298658 100644 --- a/dcmdata/tests/tpread.cc +++ b/dcmdata/tests/tpread.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -312,7 +312,6 @@ static OFCondition randomRead(OFRandom& rnd, DcmDataset *dset, unsigned char *bu OFTEST(dcmdata_partialElementAccess) { - /* make sure data dictionary is loaded */ if (!dcmDataDict.isDictionaryLoaded()) { diff --git a/dcmdata/tests/tsequen.cc b/dcmdata/tests/tsequen.cc new file mode 100644 index 00000000..c9039999 --- /dev/null +++ b/dcmdata/tests/tsequen.cc @@ -0,0 +1,100 @@ +/* + * + * Copyright (C) 2019, J. Riesmeier, Oldenburg, Germany + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for class DcmSequence and DcmPixelSequence + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcpixseq.h" +#include "dcmtk/dcmdata/dcdeftag.h" + + +#define NUMBER_OF_ITEMS 99999 + + +OFTEST(dcmdata_sequenceInsert) +{ + DcmSequenceOfItems sequence(DCM_OtherPatientIDsSequence); + /* add a large number of items to the sequence */ + unsigned long counter = 0; + for (unsigned long i = 0; i < NUMBER_OF_ITEMS; ++i) + { + if (sequence.insert(new DcmItem()).good()) + ++counter; + } + /* check whether that worked (for-loop shouldn't take too long) */ + OFCHECK_EQUAL(counter, NUMBER_OF_ITEMS); + /* access specific items (performance should be no issue) */ + OFCHECK(sequence.getItem(0) != NULL); + OFCHECK(sequence.getItem(2) != NULL); + OFCHECK(sequence.getItem(NUMBER_OF_ITEMS) == NULL); + OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 1) != NULL); + OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 2) != NULL); +} + + +OFTEST(dcmdata_pixelSequenceInsert) +{ + DcmPixelItem *pixelItem = NULL; + DcmPixelSequence pixelSequence(DCM_PixelData); + /* add a large number of items to the sequence */ + unsigned long counter = 0; + for (unsigned long i = 0; i < NUMBER_OF_ITEMS; ++i) + { + if (pixelSequence.insert(new DcmPixelItem(DcmTag(DCM_Item, EVR_OB))).good()) + ++counter; + } + /* check whether that worked (for-loop shouldn't take too long) */ + OFCHECK_EQUAL(counter, NUMBER_OF_ITEMS); + /* access specific items (performance should be no issue) */ + OFCHECK(pixelSequence.getItem(pixelItem, 0).good()); + OFCHECK(pixelSequence.getItem(pixelItem, 2).good()); + OFCHECK(pixelSequence.getItem(pixelItem, NUMBER_OF_ITEMS).bad()); + OFCHECK(pixelSequence.getItem(pixelItem, NUMBER_OF_ITEMS - 1).good()); + OFCHECK(pixelSequence.getItem(pixelItem, NUMBER_OF_ITEMS - 2).good()); +} + + +OFTEST(dcmdata_findAndGetSequenceItem) +{ + DcmDataset dataset; + DcmItem *item = NULL; + /* first, create a dataset with a sequence and a pixel sequence */ + OFCHECK(dataset.insertSequenceItem(DCM_OtherPatientIDsSequence, new DcmItem()).good()); + OFCHECK(dataset.insertSequenceItem(DCM_PixelData, new DcmItem()).good()); + /* try to retrieve the item from the sequence elements */ + OFCHECK(dataset.findAndGetSequenceItem(DCM_OtherPatientIDsSequence, item).good()); + OFCHECK(dataset.findAndGetSequenceItem(DCM_PixelData, item).good()); + /* the following should fail */ + OFCHECK(dataset.findAndGetSequenceItem(DCM_OtherPatientIDsSequence, item, 1).bad()); + OFCHECK(dataset.findAndGetSequenceItem(DCM_PixelData, item, 1).bad()); + /* then, try to create the items by some other means */ + OFCHECK(dataset.findOrCreateSequenceItem(DCM_OtherPatientIDsSequence, item, 1).good()); + OFCHECK(dataset.findOrCreateSequenceItem(DCM_PixelData, item, 1).good()); + /* now, it should work */ + OFCHECK(dataset.findAndGetSequenceItem(DCM_OtherPatientIDsSequence, item, 1).good()); + OFCHECK(dataset.findAndGetSequenceItem(DCM_PixelData, item, 1).good()); +} diff --git a/dcmdata/tests/tvrcomp.cc b/dcmdata/tests/tvrcomp.cc index a0b3cc73..d8100e30 100644 --- a/dcmdata/tests/tvrcomp.cc +++ b/dcmdata/tests/tvrcomp.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2019, OFFIS e.V. + * Copyright (C) 2015-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -66,6 +66,7 @@ #include "dcmtk/dcmdata/dcovlay.h" #include "dcmtk/dcmdata/dcpixel.h" #include "dcmtk/dcmdata/dcpixseq.h" +#include "dcmtk/dcmdata/dcdict.h" template @@ -845,6 +846,13 @@ static void checkDcmItemAndSequences() OFTEST(dcmdata_VRCompare) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + // Check the different String-based VRs (in the sense that the method // putAndInsertOFStringArray() can be used by the test method for initializing // the test values. diff --git a/dcmdata/tests/tvrdatim.cc b/dcmdata/tests/tvrdatim.cc index 16d21cfa..2f90bf5f 100644 --- a/dcmdata/tests/tvrdatim.cc +++ b/dcmdata/tests/tvrdatim.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2013, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,7 @@ #include "dcmtk/dcmdata/dcvrtm.h" #include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcdict.h" #define CHECK_EQUAL(string) do { \ strstream << OFStringStream_ends; \ @@ -44,6 +45,13 @@ OFTEST(dcmdata_dateTime) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + double timeZone; OFDate dateVal; OFTime timeVal; diff --git a/dcmdata/tests/tvrds.cc b/dcmdata/tests/tvrds.cc index 8c3a15ff..a9132a34 100644 --- a/dcmdata/tests/tvrds.cc +++ b/dcmdata/tests/tvrds.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -25,11 +25,12 @@ #include "dcmtk/ofstd/oftest.h" #include "dcmtk/dcmdata/dcvrds.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" OFTEST(dcmdata_decimalString_1) { - DcmDecimalString decStr(DCM_ContourData); + DcmDecimalString decStr(DCM_ContourData, EVR_DS); OFVector doubleVals; OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01").good()); OFCHECK(decStr.getFloat64Vector(doubleVals).good()); @@ -44,7 +45,7 @@ OFTEST(dcmdata_decimalString_1) OFTEST(dcmdata_decimalString_2) { - DcmDecimalString decStr(DCM_ContourData); + DcmDecimalString decStr(DCM_ContourData, EVR_DS); OFVector doubleVals; /* insert a NULL byte into the string */ OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34).good()); @@ -60,7 +61,7 @@ OFTEST(dcmdata_decimalString_2) OFTEST(dcmdata_decimalString_3) { - DcmDecimalString decStr(DCM_ContourData); + DcmDecimalString decStr(DCM_ContourData, EVR_DS); OFVector doubleVals; /* insert a NULL byte into the string */ OFCHECK(decStr.putOFStringArray(OFString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34)).good()); @@ -76,7 +77,7 @@ OFTEST(dcmdata_decimalString_3) OFTEST(dcmdata_decimalString_4) { - DcmDecimalString decStr(DCM_ContourData); + DcmDecimalString decStr(DCM_ContourData, EVR_DS); OFVector doubleVals; OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01\\").good()); OFCHECK_EQUAL(decStr.getVM(), 7); @@ -89,3 +90,79 @@ OFTEST(dcmdata_decimalString_4) OFCHECK(decStr.getFloat64Vector(doubleVals).bad()); OFCHECK_EQUAL(doubleVals.size(), 4); } + + +OFTEST(dcmdata_decimalString_putFloat64) +{ + // Test insertion in the beginning + OFString testStr; + DcmDecimalString decStr(DCM_ContourData, EVR_DS); + OFCHECK(decStr.putFloat64(0, 0).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0"); + + // Test insertion at the end (append) + OFCHECK(decStr.putFloat64(0.1, 1).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0\\0.1"); + + // Test insertion at the end (sparse values in the middle) + OFCHECK(decStr.putFloat64(0.5, 5).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0\\0.1\\\\\\\\0.5"); + + // Test insertion in the middle + OFCHECK(decStr.putFloat64(0.3, 3).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0\\0.1\\\\0.3\\\\0.5"); + + // Test insertion of a long float value (maximum precision) + OFCHECK(decStr.putFloat64(0.12345678901234,0).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0.123457\\0.1\\\\0.3\\\\0.5"); + + // Test insertion of long integer value + decStr.clear(); + OFCHECK(decStr.putFloat64(1234567890123456.0,0).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "1234567890123456"); + + // Test insertion of (max) long negative integer value + decStr.clear(); + OFCHECK(decStr.putFloat64(-123456789012345.0,0).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "-123456789012345"); + + // Error: Try to insert integers longer than 16 bytes + // Test insertion of long integer value + decStr.clear(); + OFCHECK(decStr.putFloat64(12345678901234567.0,0).bad()); + + // Test insertion of (max) long negative integer value + decStr.clear(); + OFCHECK(decStr.putFloat64(-1234567890123456.0,0).bad()); + + // Test insertion of a long float value (maximum precision) + decStr.clear(); + OFCHECK(decStr.putFloat64Prec(0.12345678901234, 0, 14).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0.12345678901234"); + + // Error: Test insertion of a long float value (> maximum precision which would + // result in a DS value > 16 chars. + decStr.clear(); + OFCHECK(decStr.putFloat64Prec(0.123456789012345, 0, 15).bad()); + decStr.getOFStringArray(testStr); + + // Test whether trailing zeroes are kept if desired + decStr.clear(); + OFCHECK(decStr.putFloat64Prec(0.123400, 0, 6, OFFalse).good()); + decStr.getOFStringArray(testStr); + OFCHECK(testStr == "0.123400"); + + // Check DcmItem::putFloat64() for Decimal Strings + DcmItem item; + OFCHECK(item.putAndInsertFloat64(DcmTag(DCM_ContourData, EVR_DS), 0.1).good()); + OFCHECK(item.findAndGetOFStringArray(DCM_ContourData, testStr).good()); + OFCHECK(testStr == "0.1"); +} diff --git a/dcmect/CMakeLists.txt b/dcmect/CMakeLists.txt new file mode 100644 index 00000000..a5023d25 --- /dev/null +++ b/dcmect/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +project(dcmect) + +# declare include directories which hold for all subdirectories +include_directories("${dcmect_SOURCE_DIR}/include" "${dcmfg_SOURCE_DIR}/include" "${dcmiod_SOURCE_DIR}/include" "${dcmdata_SOURCE_DIR}/include" "${ofstd_SOURCE_DIR}/include" "${oflog_SOURCE_DIR}/include" ${ZLIB_INCDIR}) + +# recurse into subdirectories +foreach(SUBDIR libsrc include tests) + add_subdirectory(${SUBDIR}) +endforeach() diff --git a/dcmect/Makefile.in b/dcmect/Makefile.in new file mode 100644 index 00000000..d17d476b --- /dev/null +++ b/dcmect/Makefile.in @@ -0,0 +1,86 @@ +# +# Makefile for dcmect +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all tests-all + +install: install-doc install-support + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmect/configure b/dcmect/configure new file mode 100755 index 00000000..3877a6a1 --- /dev/null +++ b/dcmect/configure @@ -0,0 +1,53 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + diff --git a/dcmect/data/Makefile.in b/dcmect/data/Makefile.in new file mode 100644 index 00000000..8e3825a3 --- /dev/null +++ b/dcmect/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmect/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmect/docs/Makefile.in b/dcmect/docs/Makefile.in new file mode 100644 index 00000000..159073c8 --- /dev/null +++ b/dcmect/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmect/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmect/docs/dcmect.dox b/dcmect/docs/dcmect.dox new file mode 100644 index 00000000..bc0c9841 --- /dev/null +++ b/dcmect/docs/dcmect.dox @@ -0,0 +1,180 @@ +/*! + +\page mod_dcmect dcmect: a library for working with Enhanced CT objects + +\tableofcontents + +\section dcmect_introduction Introduction + +This module contains classes to deal with DICOM Enhanced CT objects. It is able +to create, load and save them. Several checks (as possible) make sure +that only valid Enhanced CT objects are written. This module makes heavy use of +the \ref mod_dcmiod "dcmiod" module for managing common IOD attribute as well +as the \ref mod_dcmfg "dcmfg" module to manage the functional groups required +forEnhanced CT objects. + +The main class of this module is: +\li \b EctEnhancedCT + +\section dcmect_howto_use_dcmect How to use dcmect + +The \ref mod_dcmect "dcmect" module offers a main class, \b EctEnhancedCT, +that should be used as a starting point to load or create Enhanced CT objects. +The \b EctEnhancedCT class manages its data in a similar way as the related +Enhanced CT IOD is organized in the standard. It holds a list of modules +(see \ref dcmect_supported_modules) and a set of functional group macros +(see \ref dcmect_supported_functional_group_macros) that together make up +the Enhanced CT object. + +\subsection dcmect_creation Creation + +In order to create a new Enhanced CT object from scratch, a factory method +EctEnhancedCT::create() must be used (regular constructor is protected)). +create() asks for some required information that is needed in any case to +create valid Enhanced CT objects. + +Afterwards, the various attributes in the supported modules can be set. +There is a get() method for each Module that returns a reference, e.g. +EctEnhancedCT::getIODPatientModule() to retrieve the Patient Module in +order to set the attribute Patient's Name (IODPatientModule::setPatientName()) + +An exception are the attributes of the Enhanced CT Image Module which can be +set directly using set() methods on the \b EctEnhancedCT class, +e.g. EctEnhancedCT::setISOCenterPosition(). + +Functional Groups are added in two ways: + -# EctEnhancedCT::addForAllFrames() adds a Functional Group as "shared", + i.e. as being valid for all frames that will be part of this Enhanced CT + object + -# EctEnhancedCT::Frames::addFrame() adds a new frame with pixel data + and also takes a set of functional groups that should be added as + "per-frame". + +After constructing the Enhanced CT object it can be written to a \b DcmItem +or to a DICOM file (EctEnhancedCT::writeDataset() versus EctEnhancedCT::saveFile()). + +\subsection dcmect_reading Reading + +An existing Enhanced CT object can be read using the static methods +EctEnhancedCT::loadFile() (load from DICOM file) or EctEnhancedCT::loadDataset() +(reading from an existing \b DcmItem object in memory). + +For compression see section \ref dcmect_compression "on compression". + +\subsection dcmect_saving Saving + +An existing Enhanced CT object can be written using the methods +EctEnhancedCT::saveFile() (save to DICOM file) or EctEnhancedCT::writeDataset() +(writing to an existing \b DcmItem object in memory). By default, EctEnhancedCT +writes uncompressed files in transfer syntax Little Endian Explicit. + +For compression section \ref dcmect_compression "on compression". + +\subsection dcmect_modification Modification + +An existing \b EctEnhancedCT object can be modified in memory using the methods +described above. Note that modification must be done careful and might lead to +inconsistent objects. That's why it is not the recommended to modify existing +objects with the \ref mod_dcmect "dcmect" module. + +\subsection dcmect_code_example Code Example + +The dcmect/tests directory contains a file called t_roundtrip.cc which contains +code that creates, writes and reads a Enhanced CT object so it is a quite +complete demo case that shows how to use \ref mod_dcmect "dcmect" module. + +\subsection dcmect_compression Compression + +The EctEnhancedCT works on uncompressed pixel data. Therefore it first tries +to decompress a file that is encoded using a compressed ("encapsulated") +transfer syntax. + +DCMTK supports various compressed transfer syntaxes, however, the related +codecs that perform compression or decompression must be registered first +by the application that wants to use them. EctEnhancedCT does not automatically +register those codecs but leaves this to the user of the module. Once the +codecs are registered, EctEnhancedCT will make use of them when trying to +decompress the compressed dataset. + +See for example the \ref mod_dcmjpeg "dcmjpeg module" to see how registering +(and later deregistering) codecs work. + +When sving, EctEnhancedCT::saveFile() writes the file in Little Endian Explicit +transfer syntax. By setting its parameter \em writeXfer to a compressed transfer +syntax, \ref mod_dcmect "dcmect" tries to compress the file before writing. As when +reading a dataset or file, this only works if the user registered the related +decompression codecs first. + +\section dcmect_supported_modules Supported Modules + +The following modules of the Enhanced CT IOD are supported: + +\li Patient Module +\li Patient Study Module +\li General Study Module +\li General Series Module +\li Enhanced CT Series Module +\li Frame of Reference Module +\li Synchronization Module +\li General Equipment Module +\li Enhanced General Equipment Module +\li Image Pixel Module +\li Multi-frame Functional Groups Module +\li Multi-frame Dimension Module +\li Acquisition Context Module +\li Enhanced CT Module +\li SOP Common Module +\li Common Instance Reference Module + + The following modules are \e not (yet) supported: + \li Enhanced Contrast/Bolus Module + \li Cardiac Synchronization Module + \li Respiratory Synchronization Module + \li Supplemental Palette Color Lookup Table Module + \li Device Module + \li Specimen Module + \li Enhanced Multi-energy CT Acquisition Module + \li ICC Profile Module + \li Frame Extraction Module + + There might be further unsupported optional modules that have been added to + the DICOM Standard after the last update of this documentation. + + \section dcmect_supported_functional_group_macros Supported Functional Group Macros + + The following functional group macros are supported: + +\li Pixel Measures +\li Frame Content +\li Plane Position (Patient) +\li Plane Orientation (Patient) +\li Derivation Image +\li Frame Anatomy +\li Frame VOI LUT +\li Real World Value Mapping +\li Irradiation Event Identification +\li CT Image Frame Type +\li CT Acquisition Type +\li CT Acquisition Details +\li CT Table Dynamics +\li CT Position +\li CT Geometry +\li CT Reconstruction +\li CT Exposure +\li CT X-Ray Details +\li CT Pixel Value Transformation +\li CT Additional X-Ray Source +\li Temporal Position + +The following functional group macros are \e not (yet) support: +\li Referenced Image +\li Cardiac Synchronization +\li Contrast/Bolus Usage +\li Respiratory Synchronization +\li Multi-energy CT Processing +\li Multi-energy CT Characteristics + +There might be further unsupported optional functional group macros that have +been added to the DICOM Standard after the last update of this documentation. + +*/ diff --git a/dcmect/etc/Makefile.in b/dcmect/etc/Makefile.in new file mode 100644 index 00000000..cca88ee4 --- /dev/null +++ b/dcmect/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmect/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmect/include/CMakeLists.txt b/dcmect/include/CMakeLists.txt new file mode 100644 index 00000000..ca73554f --- /dev/null +++ b/dcmect/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +install(DIRECTORY dcmtk/dcmect DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/dcmtk" COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmect/include/Makefile.in b/dcmect/include/Makefile.in new file mode 100644 index 00000000..7bf09157 --- /dev/null +++ b/dcmect/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmect/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmect + for file in dcmtk/dcmect/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmect ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmect/include/dcmtk/dcmect/def.h b/dcmect/include/dcmtk/dcmect/def.h new file mode 100644 index 00000000..c5c6a49a --- /dev/null +++ b/dcmect/include/dcmtk/dcmect/def.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Contains preprocessor definitions + * + */ + +#ifndef DCMECT_DEF_H +#define DCMECT_DEF_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofdefine.h" + +// definitions for DLL/shared library exports + +#ifdef dcmect_EXPORTS +#define DCMTK_DCMECT_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMECT_EXPORT DCMTK_DECL_IMPORT +#endif + +#endif // DCMECT_DEF_H diff --git a/dcmect/include/dcmtk/dcmect/enhanced_ct.h b/dcmect/include/dcmtk/dcmect/enhanced_ct.h new file mode 100644 index 00000000..5e586cce --- /dev/null +++ b/dcmect/include/dcmtk/dcmect/enhanced_ct.h @@ -0,0 +1,808 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Class representing an Enhanced CT object + * + */ + +#ifndef DCMECT_ENHANCED_CT_H +#define DCMECT_ENHANCED_CT_H + +#include "dcmtk/config/osconfig.h" // include OS configuration first + +#include "dcmtk/dcmect/def.h" +#include "dcmtk/dcmect/types.h" // for Enhanced CT data types +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/dcmiod/iodimage.h" +#include "dcmtk/dcmiod/modacquisitioncontext.h" +#include "dcmtk/dcmiod/modenhequipment.h" +#include "dcmtk/dcmiod/modequipment.h" +#include "dcmtk/dcmiod/modimagepixel.h" +#include "dcmtk/dcmiod/modmultiframedimension.h" +#include "dcmtk/dcmiod/modmultiframefg.h" +#include "dcmtk/dcmiod/modsynchronisation.h" + +class IODGeneralEquipmentModule; +class FGBase; +class ConcatenationLoader; +class ConcatenationCreator; + +template +class IODImagePixelModule; + +/** Class representing an object of the "Enhanced CT SOP Class". + * Supported Modules: + * - Patient (via iodimage.h) + * - Patient Study (via iodimage.h) + * - General Study (via iodimage.h) + * - General Series (via iodimage.h) + * - Enhanced CT Series (via this class) + * - Frame of Reference (via iodimage.h) + * - Synchronization (via modsynchronisation.h) + * - General Equipment (via iodimage.h) + * - Enhanced General Equipment (via modenhequipment.h) + * - Image Pixel (via this class) + * - Multi-frame Functional Groups (via modmultiframefg.h) + * - Multi-frame Dimension (via modmultiframedimension.h) + * - Acquisition Context (via modacquisitioncontext.h) + * - Enhanced CT (via mod_enhanced_ct.h) + * - SOP Common (via iodimage.h) + * - Common Instance Reference (via iodimage.h) + * + * Modules that are not supported: + * - Enhanced Contrast/Bolus + * - Cardiac Synchronization + * - Respiratory Synchronization + * - Supplemental Palette Color Lookup Table + * - Device + * - Specimen + * - Enhanced Multi-energy CT Acquisition + * - ICC Profile + * - Frame Extraction + */ +class DCMTK_DCMECT_EXPORT EctEnhancedCT : public DcmIODImage, IODImagePixelModule > +{ + +public: + /** Inner class that offers typed interface to bulk data. + */ + template + class DCMTK_DCMECT_EXPORT Frames + { + public: + /// Binary pixel type + typedef PixelType pixel_type; + + /** Method that adds a frame to the Enhanced CT using the underlying + * binary data type. + * @param data The frame data + * @param numPixels The number of pixels (rows * columns) of the frame + * @param perFrameInformation The per-frame functional groups applying for + * @return EC_Normal if adding was successful, error otherwise + */ + OFCondition addFrame(PixelType* data, const size_t numPixels, const OFVector& perFrameInformation); + + /** Type-specific getFrame() method that returns Sint16 or Uint16 (whatever + * is used in this Enhanced CT) + * @param frameNumber The frame number to get, starting from 0 + * @return Pointer to typed pixel data + */ + PixelType* getFrame(const size_t frameNumber); + + private: + /// Make sure the Enhanced CT object (and no one else) can use the constructor below. + friend class EctEnhancedCT; + + /** Create Frames object in EctEnhancedCT (see friend declaration above) + * @param ct The CT object that will contain the frames + */ + Frames(EctEnhancedCT& ct); + + /// Reference to Enhanced CT object in order to access its pixel data + EctEnhancedCT& m_CT; + }; + + /** Frames can contain Uint16, Sint16 or nothing (i.e.\ error condition) + * at all (in that case OFCondition denotes a corresponding error) + */ + typedef OFvariant, Frames > FramesType; + + // -------------------- destruction ------------------------------- + + /** Destructor, frees memory + */ + virtual ~EctEnhancedCT(); + + // -------------------- loading and saving --------------------- + + /** Static method to load a Enhanced CT object from a file. + * The memory of the resulting Enhanced CT object has to be freed by the + * caller. + * @param filename The file to read from + * @param ct The resulting Enhanced CT object. NULL if dataset + * could not be read successfully. + * @return EC_Normal if reading was successful, error otherwise + */ + static OFCondition loadFile(const OFString& filename, EctEnhancedCT*& ct); + + /** Static method to load a Enhanced CT object from a dataset object. + * The memory of the resulting Enhanced CT object has to be freed by the + * caller. + * @param dataset The dataset to read from + * @param ct The resulting Enhanced CT object. NULL if dataset + * could not be read successfully. + * @return EC_Normal if reading was successful, error otherwise + */ + static OFCondition loadDataset(DcmDataset& dataset, EctEnhancedCT*& ct); + + /** Static method to load a concatenation of a DICOM Enhanced CT instance + * into a EctEnhancedCT object. + * @param cl The ConcatenationLoader instance to be used. Must be configured + * so that load() can be called. + * @param concatenationUID The Concatenation UID identifying the Concatenation + * within the Concatenations know to ConcatenationLoader cl. + * @param ct The resulting Enhanced CT object, if loading was successful + * @return EC_Normal if loading was successful, error otherwise + */ + static OFCondition loadConcatenation(ConcatenationLoader& cl, const OFString& concatenationUID, EctEnhancedCT*& ct); + + /** Save current object to given filename + * @param filename The file to write to + * @param writeXfer The transfer syntax to be used + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition saveFile(const OFString& filename, const E_TransferSyntax writeXfer = EXS_LittleEndianExplicit); + + /** Write current object to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition writeDataset(DcmItem& dataset); + + /** Write current object to a Concatenation. + * @param cc The Concatenation Creator object to be used. Must be configured + * so that writeNextInstance() is ready to be called. + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition writeConcatenation(ConcatenationCreator& cc); + + /** If enabled, functional group structure is checked before actual writing + * is performed in the write() method. Checking might be time consuming + * on functional groups with many frames, though disabling might result in + * invalid functional group structures. Disabling should only be done if the + * user knows that the functional groups are valid, wants to to adapt the + * functional groups manually after calling write() or knows what he's doing + * otherwise.
+ * Per default, checking is enabled. + * @param doCheck If OFTrue, checking will be performed. If OFFalse, + * no checks are performed. + */ + virtual void setCheckFGOnWrite(const OFBool doCheck); + + /** Returns whether functional group structure is checked before actual + * writing is performed in the write() method. + * @return OFTrue if checking is performed, OFFalse otherwise + */ + virtual OFBool getCheckFGOnWrite(); + + // -------------------- creation --------------------- + + /** Factory method to create an Enhanced CT object from the minimal + * set of information required. The actual frame data is + * added separately. + * The memory of the resulting Enhanced CT object has to be freed by the + * caller. + * @param ct The resulting Enhanced CT object if provided data is + * valid. Otherwise NULL is returned. + * @param rows Number of rows of Enhanced CT frame data + * @param columns Number of rows of Enhanced CT frame data + * @param signedPixelData Denotes if pixel data is signed (OFTrue, Sint16) or + * unsigned (OFFalse, Uint16) + * @param imageType1 First value for tag Image Type (0008,0008) + * @param imageType3 Third Value for tag Image Type (0008,0008). See + * EctTypes::DT_ImageType3_... for Defined Terms. + * @param imageType4 Fourth Value for tag Image Type (0008,0008). See + * EctTypes::DT_ImageType4_... for Defined Terms. + * @param instanceNumber The value for tag Instance Number (0020,0013). + * @param contentQualification The value for tag Content Qualification + * (0018,9004). + * @param pixelPresentation The value for tag Pixel Presentation (0008,9205). + * @param volumetricProperties The value for tag Volumetric Properties (0008,9206). + * @param volumeBasedCalculationTechnique The value for tag Volume Based Calculation + * Technique (0008,9207). + * @param equipmentInfo Equipment that is responsible for creating the EctEnhancedCT + * @param acquisitionDateTime The date/time when the acquisition of data started. + * Required if value 1 of Image Type is is ORIGINAL or MIXED; may be present + * otherwise. If empty, value will not be set (default) + * @param acquisitionDuration The time in seconds needed to complete the acquisition of data. + * Required if value 1 of Image Type is is ORIGINAL or MIXED; may be present + * otherwise. If negative, value will not be set (default) + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition create(EctEnhancedCT*& ct, + const Uint16 rows, + const Uint16 columns, + const OFBool signedPixelData, + const EctTypes::E_ImageType1 imageType1, + const OFString& imageType3, + const OFString& imageType4, + const OFString& instanceNumber, + const EctTypes::E_ContentQualification contentQualification, + const EctTypes::E_PixelPresentation pixelPresentation, + const EctTypes::E_VolumetricProperties volumetricProperties, + const OFString& volumeBasedCalculationTechnique, + const IODEnhGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const OFString& acquisitionDateTime = "", + const Float64& acquisitionDuration = -1.0); + + // -------------------- access --------------------- + + /** Get number of frames, based on the number of items in the shared + * functional functional groups sequence (i.e.\ the attribute Number of + * Frames) is not trusted). + * @return The number of frames handled by this object + */ + size_t getNumberOfFrames() const; + + /** Perform some basic checking. This method is also invoked when + * writing the object to a DICOM dataset or file. + * @param checkFGStructure If OFTrue (default), structure of functional + * groups is checked, too. + * @return OFTrue, if no errors were found, OFFalse otherwise. + */ + virtual OFBool check(const OFBool checkFGStructure = OFTrue); + + /** Get access to functional groups. This is meant for reading data from + * functional groups that are not actively managed, i.e.\ made accessible by + * EctEnhancedCT. In rare cases, however, it makes sense to access it + * for writing too, e.g.\ in order to add Stacks; use with care! + * @return Reference to the functional groups + */ + virtual FGInterface& getFunctionalGroups(); + + /** Get reference t Concatenation information + * @return Reference to ConcatenationInfo object + */ + virtual IODMultiFrameFGModule::ConcatenationInfo& getConcatenationInfo(); + + // -------------------- modification --------------------- + + /** Add a functional group for all frames + * @param group The group to be added as shared functional group. The + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition addForAllFrames(const FGBase& group); + + /** Return reference to multi-fame dimension module + * @return Reference to multi-frame dimension module + */ + virtual IODMultiframeDimensionModule& getDimensions(); + + /** Return Frames + * @return All frames currently assigned to the object + */ + virtual FramesType getFrames(); + + /** Import Patient, Study, and Frame of Reference level information from the + * given item. The method does only import Frame of Reference if Frame of + * Reference (FoR) UID is found in the image (and no error is reported if not). + * The reason is that if the source images of the Enhanced CT do have an + * FoR, the Enhanced CT object must have the same one, so we must import it. + * If the images do not have an FoR, we must not try at all importing it. + * If the log stream is set and valid the, the reason for any error might be + * obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition importFromSourceImage(DcmItem& dataset, const OFBool takeOverCharset = OFTrue); + + /** Import Patient, Study, and Frame of Reference level information from the + * given item. The method does only import Frame of Reference if Frame of + * Reference UID is found in the image (and no error is reported if not). + * The reason is that if the source images of the Enhanced CT do have an + * FoR, the Enhanced CT object must have the same one, so we must import it. + * If the images do not have an FoR, we must not try at all importing it. + * The current content of this object is not deleted before reading. + * If the log stream is set and valid the, the reason for any error might be + * obtained from the error/warning output. + * @param filename Reference to DICOM dataset from which the document + * should be read + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition importFromSourceImage(const OFString& filename, const OFBool takeOverCharset = OFTrue); + + // ---------------------- Get / Set modules ---------------------- + + /** Get Patient Module + * @return a reference to the IOD Patient Module + */ + virtual IODPatientModule& getIODPatientModule(); + + /** Get General Study Module + * @return a reference to the IOD General Study Module + */ + virtual IODGeneralStudyModule& getIODGeneralStudyModule(); + + /** Get Patient Study Module + * @return a reference to the IOD Patient Study Module + */ + virtual IODPatientStudyModule& getIODPatientStudyModule(); + + /** Get General Series Module + * @return a reference to the IOD General Series Module + */ + virtual IODGeneralSeriesModule& getIODGeneralSeriesModule(); + + /** Get Frame of Reference Module + * @return a reference to the IOD Frame of Reference Module + */ + virtual IODFoRModule& getIODFrameOfReferenceModule(); + + /** Get Synchronization Module + * @return a reference to the IOD Frame of Reference Module + */ + virtual IODSynchronizationModule& getIODSynchronizationModule(); + + /** Set whether Synchronization Module will be enabled when writing + * the Enhanced CT object. + * @param enabled If OFTrue, Synchronization Module will be written, + * otherwise not. + */ + virtual void setIODSynchronisationModuleEnabled(const OFBool enabled); + + /** Returns whether Synchronization Module is enabled for writing + * the Enhanced CT object. + * @return OFTrue, if Synchronization Module will be written, + * OFFalse otherwise. + */ + virtual OFBool getIODSynchronisationModuleEnabled(); + + /** Get General Equipment Module + * @return a reference to the General Equipment Module + */ + virtual IODGeneralEquipmentModule& getIODGeneralEquipmentModule(); + + /** Get Enhanced General Equipment Module + * @return a reference to the Enhanced General Equipment Module + */ + virtual IODEnhGeneralEquipmentModule& getIODEnhGeneralEquipmentModule(); + + /** Get Multi-frame Functional Groups Module + * @return a reference to the Multi-frame Functional Groups Module + */ + virtual IODMultiFrameFGModule& getIODMultiFrameFGModule(); + + /** Get Multi-frame Dimension Module + * @return a reference to the Multi-frame Dimension Module + */ + virtual IODMultiframeDimensionModule& getIODMultiframeDimensionModule(); + + /** Get Acquisition Context Module + * @return a reference to the Acquisition Context Module + */ + virtual IODAcquisitionContextModule& getIODAcquisitionContextModule(); + + /** Get Common Instance Reference Module + * @return a reference to the Common Instance Reference Module + */ + virtual IODCommonInstanceReferenceModule& getIODCommonInstanceReferenceModule(); + + /** Get SOP Common Module + * @return a reference to the SOP Common Module + */ + virtual IODSOPCommonModule& getIODSOPCommonModule(); + + // ---------------- CT Image level getter() -------------------- + + /** Get Image Type + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getImageType(OFString& value, const long pos); + + /** Get Acquisition Number + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionNumber(Sint32& value, const unsigned long pos); + + /** Get Acquisition Number + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionNumber(OFString& value, const long pos); + + /** Get Acquisition DateTime + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionDateTime(OFString& value, const long pos); + + /** Get Acquisition Duration + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionDuration(Float64& value, const unsigned long pos); + + /** Get Acquisition Duration + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionDuration(OFString& value, const long pos); + + /** Get Content Qualification + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getContentQualification(OFString& value, const long pos); + + /** Get Image Comments + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getImageComments(OFString& value, const long pos); + + /** Get Burned In Annotation (if filled in correctly by creator, this + * should always be "NO"). + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getBurnedInAnnotation(OFString& value, const long pos); + + /** Get Recognizable Visual Features + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRecognizableVisualFeatures(OFString& value, const long pos); + + /** Get Lossy Image Compression + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getLossyImageCompression(OFString& value, const long pos); + + /** Get Lossy Image Compression Ratio + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(Float64& value, const unsigned long pos); + + /** Get Lossy Image Compression Ratio + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(OFString& value, const long pos); + + /** Get Lossy Image Compression Method + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getLossyImageCompressionMethod(OFString& value, const long pos); + + /** Get Presentation LUT Shape + * @param value Reference to variable that should hold the result. Should + * always return the value "IDENTITY" if creator filled in the value + * correctly. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getPresentationLUTShape(OFString& value, const long pos); + + /** Get Multi-Energy CT Acquisition + * @param value Reference to variable that should hold the result. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getMultiEnergyCTAcquisition(OFString& value, const long pos); + + /** Get Pixel Presentation + * @param value Reference to variable that should hold the result. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getPixelPresentation(OFString& value, const long pos); + + /** Get Volumetric Properties + * @param value Reference to variable that should hold the result. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getVolumetricProperties(OFString& value, const long pos); + + /** Get Volume Based Calculation Technique + * @param value Reference to variable that should hold the result. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getVolumeBasedCalculationTechnique(OFString& value, const long pos); + + /** Get Isocenter Position + * @param value Reference to variable that should hold the result. + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getIsocenterPosition(OFString& value, const long pos); + + /** Get Isocenter Position + * @param values Reference to variable that should hold the result. Should + * hold 3 values if not empty and filled correctly by the creator of + * the Enhanced CT object. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getIsocenterPosition(OFVector& values); + + /** Get number of rows + * @param rows The number of rows (output) + * @return EC_Normal if getting was successful, error otherwise + */ + virtual OFCondition getRows(Uint16& rows); + + /** Get number of cols + * @param cols The number of columns (output) + * @return EC_Normal if getting was successful, error otherwise + */ + virtual OFCondition getColumns(Uint16& cols); + + // ---------------- Setters() -------------------- + + virtual OFCondition setImageType(const OFString& value, const OFBool check = OFTrue); + + virtual OFCondition setAcquisitionNumber(const OFString& value, const OFBool check = OFTrue); + + virtual OFCondition setAcquisitionDateTime(const OFString& value, const OFBool check = OFTrue); + + virtual OFCondition setAcquisitionDuration(const Float64& value, const OFBool check = OFTrue); + + virtual OFCondition setContentQualification(const EctTypes::E_ContentQualification value, + const OFBool check = OFTrue); + + virtual OFCondition setImageComments(const OFString& value, const OFBool check = OFTrue); + + virtual OFCondition setRecognizableVisualFeatures(const EctTypes::E_RecognizableVisualFeatures value, + const OFBool check = OFTrue); + + /** Set lossy compression flag of the image to "00" or "01" If set to "01", + * ratios and methods have to be provided, too. + * @param isLossy If OFTrue, Lossy Image Compression is set to "01", otherwise + * to "00". + * @param ratios Compression ratios (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. The parameter is ignored if isLossy is OFFalse. + * @param methods Methods (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. The parameter is ignored if isLossy is OFFalse. + * @param check If OFTrue, the data provided is checked for validity + * @return EC_Normal if lossy compression info could be set, error code otherwise + */ + virtual OFCondition setLossyImageCompression(const OFBool isLossy, + const OFString& ratios = "", + const OFString& methods = "", + const OFBool check = OFTrue); + + /** Set Isocenter Position + * @param values Value that should be set + * @param check If OFTrue, basic checks are performed whether the values are + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setISOCenterPosition(const OFVector& values, const OFBool check = OFTrue); + + /** Set Isocenter Position + * @param value Value that should be set + * @param check If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setISOCenterPosition(const OFString& value, const OFBool check = OFTrue); + + /** Set Multi-Energy CT Acquisition + * @param value Value that should be set + * @param check If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setMultiEnergyCTAcquisition(const OFString& value, const OFBool check = OFTrue); + + /** Set Pixel Presentation + * @param value Value that should be set + * @param check Ignored in current implementation (enum value is always checked for validity). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setPixelPresentation(const EctTypes::E_PixelPresentation value, const OFBool check = OFTrue); + + /** Set Volumetric Properties + * @param value Value that should be set + * @param check Ignored in current implementation (enum value is always checked for validity). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setVolumetricProperties(const EctTypes::E_VolumetricProperties value, + const OFBool check = OFTrue); + + /** Set Volume Based Calculation Technique + * @param value Value that should be set + * @param check If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setVolumeBasedCalculationTechnique(const OFString& value, const OFBool check = OFTrue); + +protected: + /** Protected default constructor. Library users should the factory create..() + * method in order to create an object from scratch + */ + template + EctEnhancedCT(OFin_place_type_t(ImagePixel)); + + /** Overwrites and publicly hides DcmIODImage::read() + * @param dataset The dataset to read from + * @return EC_Normal if reading succeeded, error otherwise + */ + virtual OFCondition read(DcmItem& dataset); + + /** Overwrites and publicly hides DcmIODImage::write() + * @param dataset The dataset to write to + * @return EC_Normal if writing succeeded, error otherwise + */ + virtual OFCondition write(DcmItem& dataset); + + /** Writes pixel data to item + * @param dataset The dataset to write to + * @return EC_Normal if writing succeeded, error otherwise + */ + virtual OFCondition writeGeneric(DcmItem& dataset); + + /** Read Enhanced CT's generic (not directly pixel-data related) attributes from + * DICOM dataset. + * @param dataset Reference to DICOM dataset to read from. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition readGeneric(DcmItem& dataset); + + /** General Image Module is not allowed in Enhanced CT, remove from public interface. + * @return Reference to General Image Module + */ + virtual IODGeneralImageModule& getGeneralImage() + { + return IODImage::getGeneralImage(); + } + +private: + // Forward declarations (pixel type related Visitors) + struct SetImagePixelModuleVisitor; + struct ReadVisitor; + struct WriteVisitor; + struct WriteVisitorConcatenation; + struct GetFramesVisitor; + + /// Synchronization Module + IODSynchronizationModule m_SynchronisationModule; + + /// Denote whether Synchronization Module is enabled (OFTrue) + /// or ignored (OFFalse) on writing and checking. + OFBool m_SynchronisationModuleEnabled; + + /// IODEnhancedEquipmentModule + IODEnhGeneralEquipmentModule m_EnhancedGeneralEquipmentModule; + + /// Multi-frame Functional Groups module + IODMultiFrameFGModule m_FG; + + /// Multi-frame Dimension Module + IODMultiframeDimensionModule m_DimensionModule; + + /// Acquisition Context Module + IODAcquisitionContextModule m_AcquisitionContextModule; + + /// Common Instance Reference Module + IODCommonInstanceReferenceModule m_CommonInstanceReferenceModule; + + /// Binary frame data + OFVector m_Frames; + + /// Multi-frame Functional Groups high level interface + FGInterface m_FGInterface; + + /* Image level information */ + + /// Image Type: (CS, VM 4, Type 1) + DcmCodeString m_ImageType; + + /// Instance Number: (IS, VM 1, Type 1) + DcmIntegerString m_InstanceNumber; + + /// Multi-Energy CT Acquisition: (CS VM 1, Type 3) + DcmCodeString m_MultiEnergyCTAcquisition; + + /// Pixel Presentation: (CS, VM 1, Type 1) + DcmCodeString m_PixelPresentation; + + /// Volumetric Properties: (CS, VM 1, Type 1) + DcmCodeString m_VolumetricProperties; + + /// Volume Based Calculation Technique: (CS, VM 1, Type 1) + DcmCodeString m_VolumeBasedCalculationTechnique; + + /// Acquisition Number: (IS, VM 1, Type 3) + DcmIntegerString m_AcquisitionNumber; + + /// Acquisition DateTime: (DT, VM 1, Type 1C) + DcmDateTime m_AcquisitionDateTime; + + /// Acquisition Duration: (FD, VM 1, Type 1C) + DcmFloatingPointDouble m_AcquisitionDuration; + + /// Content Qualification: (CS, VM 1, Type 1C) + DcmCodeString m_ContentQualification; + + /// Image Comments: (LT, VM 1, Type 3) + DcmLongText m_ImageComments; + + /// Burned In Annotation: (CS, VM 1, Type 1C) + DcmCodeString m_BurnedInAnnotation; + + /// Recognizable Visual Features: (CS, VM 1, Type 3) + DcmCodeString m_RecognizableVisualFeatures; + + /// Lossy Image Compression: (CS, VM 1, Type 1C) + DcmCodeString m_LossyImageCompression; + + /// Lossy Image Compression Ratio: (DS, VM 1, Type 1C) + DcmDecimalString m_LossyImageCompressionRatio; + + /// Lossy Image Compression Method: (CS, VM 1, Type 1C) + DcmCodeString m_LossyImageCompressionMethod; + + /// Presentation LUT Shape: (CS, VM 1, Type 1) + DcmCodeString m_PresentationLUTShape; + + /// Isocenter Position: (DS, VM 3, Type 3) + DcmDecimalString m_IsoCenterPosition; + + // --------------- private helper functions ------------------- + + /** Decompress the given dataset + * @param dset The dataset to be decompressed + * @return EC_Normal if decompression worked (or dataset has already been + * decompressed), IOD_EC_CannotDecompress otherwise + */ + static OFCondition decompress(DcmDataset& dset); +}; + +#endif // DCMECT_ENHANCED_CT_H diff --git a/dcmect/include/dcmtk/dcmect/types.h b/dcmect/include/dcmtk/dcmect/types.h new file mode 100644 index 00000000..102bc758 --- /dev/null +++ b/dcmect/include/dcmtk/dcmect/types.h @@ -0,0 +1,312 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Class for managing common Enhanced CT-specific types + * + */ + +#ifndef DCMECT_TYPES_H +#define DCMECT_TYPES_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmect/def.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/oflog/oflog.h" + +/*-----------------------* + * Logging * + *-----------------------*/ + +extern DCMTK_DCMECT_EXPORT OFLogger DCM_dcmectLogger; + +#define DCMECT_TRACE(msg) OFLOG_TRACE(DCM_dcmectLogger, msg) +#define DCMECT_DEBUG(msg) OFLOG_DEBUG(DCM_dcmectLogger, msg) +#define DCMECT_INFO(msg) OFLOG_INFO(DCM_dcmectLogger, msg) +#define DCMECT_WARN(msg) OFLOG_WARN(DCM_dcmectLogger, msg) +#define DCMECT_ERROR(msg) OFLOG_ERROR(DCM_dcmectLogger, msg) +#define DCMECT_FATAL(msg) OFLOG_FATAL(DCM_dcmectLogger, msg) + +// include this file in doxygen documentation + +/** @file types.h + * @brief type definitions, constants and helper classes for the dcmect module + */ + +/*----------------------* + * Constant definitions * + *----------------------*/ + +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_InvalidDimensions; +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_InvalidAttributeValue; +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_InvalidPixelInfo; +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_InvalidPixelData; +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_NoPixelData; +extern DCMTK_DCMECT_EXPORT const OFConditionConst ECT_InvalidSOPClass; + +/** General purpose class hiding global functions, constants and types in the + * Enhanced CT context from the global namespace. + */ +class DCMTK_DCMECT_EXPORT EctTypes +{ + +public: + /// Enum containing the Enumerated Values for the first value of tag Image Type (0008,0008) + enum E_ImageType1 + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_ImageType1_Empty, + /// Denotes any invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_ImageType1_Invalid, + /// Reflects the value "ORIGINAL" + E_ImageType1_Original, + /// Reflects the value "DERIVED" + E_ImageType1_Derived, + /// Reflects the value "MIXED" + E_ImageType1_Mixed + }; + + /// Enum containing the Enumerated Values for the 2nd value of tag Image Type (0008,0008) + enum E_ImageType2 + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_ImageType2_Empty, + /// Denotes any invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_ImageType2_Invalid, + /// Reflects the value "PRIMARY" which is the only valid value permitted + E_ImageType2_Primary + }; + + /// Defined Term "ANGIO" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Angio; + /// Defined Term "CARDIAC" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Cardiac; + /// Defined Term "CARDIAC_GATED" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_CardiacGated; + /// Defined Term "CARDRESP_GATED" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_CardRespGated; + /// Defined Term "DYNAMIC" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Dynamic; + /// Defined Term "FLUOROSCOPY" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Fluoroscopy; + /// Defined Term "LOCALIZER" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Localizer; + /// Defined Term "MOTION" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Motion; + /// Defined Term "PERFUSION" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Perfusion; + /// Defined Term "PRE_CONTRAST" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_PreContrast; + /// Defined Term "POST_CONTRAST" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_PostContrast; + /// Defined Term "RESP_GATED" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_RespGated; + /// Defined Term "REST" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Rest; + /// Defined Term "STATIC" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Static; + /// Defined Term "STRESS" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Stress; + /// Defined Term "VOLUME" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_Volume; + /// Defined Term "NON_PARALLEL" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_NonParallel; + /// Defined Term "WHOLE_BODY" for 3rd value of tag Image Type (0008,0008) + static const OFString DT_ImageType3_WholeBody; + + /// Defined Term "ADDITION" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Addition; + /// Defined Term "DIVISION" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Division; + /// Defined Term "MASKED" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Masked; + /// Defined Term "MAXIMUM" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Maximum; + /// Defined Term "MEAN" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Mean; + /// Defined Term "MINIMUM" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Minimum; + /// Defined Term "MULTIPLICATION" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Multiplication; + /// Defined Term "RESAMPLED" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Resampled; + /// Defined Term "STD_DEVIATION" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Std_Deviation; + /// Defined Term "SUBTRACTION" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Subtraction; + /// Defined Term "NONE" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_None; + /// Defined Term "QUANTITY" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Quantity; + /// Defined Term "MIXED" for 4th value of tag Image Type (0008,0008) + static const OFString DT_ImageType4_Mixed; + + /// Enum containing the Enumerated Values of tag Content Qualification (0018,9004) + enum E_ContentQualification + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_ContentQuali_Empty, + /// Denotes an invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_ContentQuali_Invalid, + /// Reflects the value "PRODUCT" which is the only valid value permitted + E_ContQuali_Product, + /// Reflects the value "RESEARCH" which is the only valid value permitted + E_ContQuali_Research, + /// Reflects the value "SERVICE" which is the only valid value permitted + E_ContQuali_Service + }; + + /// Enum containing the Enumerated Values of tag Burned In Annotation (0028,0301) + enum E_BurnedInAnnotation + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_BurnedInAnno_Empty, + /// Denotes an invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_BurnedInAnno_Invalid, + /// Reflects the value "NO" which is the only valid value permitted + E_BurnedInAnno_No + }; + + /// Enum containing the Enumerated Values of tag Recognizable Visual Features (0028,0302) + enum E_RecognizableVisualFeatures + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_RecoVisFeatures_Empty, + /// Denotes an invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_RecoVisFeatures_Invalid, + /// Reflects the value "YES" + E_RecoVisFeatures_Yes, + /// Reflects the value "NO" + E_RecoVisFeatures_No + }; + + /// Enum containing the Enumerated Values of tag Pixel Presentation (0008,9205) + enum E_PixelPresentation + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_PixelPres_Empty, + /// Denotes an invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_PixelPres_Invalid, + /// Reflects the value "COLOR" + E_PixelPres_Color, + /// Reflects the value "MONOCHROME" + E_PixelPres_Monochrome, + /// Reflects the value "MIXED" + E_PixelPres_Mixed, + /// Reflects the value "TRUE_COLOR" + E_PixelPres_TrueColor + }; + + /// Enum containing the Enumerated Values of tag Volumetric Properties (0008,9206) + enum E_VolumetricProperties + { + /// Denotes an empty attribute value (not permitted but may be found when reading + /// an invalid object) + E_VolProps_Empty, + /// Denotes an invalid attribute value (not permitted but may be found when reading + /// an invalid object) + E_VolProps_Invalid, + /// Reflects the value "VOLUME" + E_VolProps_Volume, + /// Reflects the value "SAMPLED" + E_VolProps_Sampled, + /// Reflects the value "DISTORTED" + E_VolProps_Distorted, + /// Reflects the value "MIXED" + E_VolProps_Mixed + }; + + /// Defined Term "MAX_IP" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_MaxIp; + /// Defined Term "MIN_IP" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_MinIp; + /// Defined Term "VOLUME_RENDER" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_VolumeRender; + /// Defined Term "SURFACE_RENDER" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_SurfaceRender; + /// Defined Term "MPR" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_Mpr; + /// Defined Term "CURVED_MPR" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_CurvedMpr; + /// Defined Term "NONE" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_None; + /// Defined Term "MIXED" for tag Volume Based Calculation Technique + static const OFString DT_VolBasedCalcTechnique_Mixed; + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString imageType1ToStr(const E_ImageType1 value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString imageType2ToStr(const E_ImageType2 value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString contentQualiToStr(const E_ContentQualification value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString burnedAnnoToStr(const E_BurnedInAnnotation value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString pixelPresToStr(const E_PixelPresentation value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString volPropsToStr(const E_VolumetricProperties value); + + /** Returns related string for given enum value. Returns empty string for + * invalid or empty values. + * @param value The enum value + * @return The related string value + */ + static OFString recoVisFeaturesToStr(const E_RecognizableVisualFeatures value); +}; + +#endif // DCMECT_TYPES_H diff --git a/dcmect/libsrc/CMakeLists.txt b/dcmect/libsrc/CMakeLists.txt new file mode 100644 index 00000000..87c450d5 --- /dev/null +++ b/dcmect/libsrc/CMakeLists.txt @@ -0,0 +1,4 @@ +# create library from source files +DCMTK_ADD_LIBRARY(dcmect enhanced_ct types) + +DCMTK_TARGET_LINK_MODULES(dcmect dcmfg dcmiod dcmdata ofstd oflog) diff --git a/dcmect/libsrc/Makefile.dep b/dcmect/libsrc/Makefile.dep new file mode 100644 index 00000000..e4f081dc --- /dev/null +++ b/dcmect/libsrc/Makefile.dep @@ -0,0 +1,284 @@ +enhanced_ct.o: enhanced_ct.cc ../include/dcmtk/dcmect/enhanced_ct.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmect/def.h ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmect/types.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \ + ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsynchronisation.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h +types.o: types.cc ../include/dcmtk/dcmect/types.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmect/def.h ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h diff --git a/dcmect/libsrc/Makefile.in b/dcmect/libsrc/Makefile.in new file mode 100644 index 00000000..c97447c1 --- /dev/null +++ b/dcmect/libsrc/Makefile.in @@ -0,0 +1,56 @@ +# +# Makefile for dcmect/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmioddir = $(top_srcdir)/../dcmiod +dcmfgdir = $(top_srcdir)/../dcmfg + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include \ + -I$(dcmdatadir)/include -I$(dcmioddir)/include \ + -I$(dcmfgdir)/include + +LOCALDEFS = + +objs = enhanced_ct.o types.o + + +library = libdcmect.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmect/libsrc/enhanced_ct.cc b/dcmect/libsrc/enhanced_ct.cc new file mode 100644 index 00000000..007cb881 --- /dev/null +++ b/dcmect/libsrc/enhanced_ct.cc @@ -0,0 +1,1225 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * + * + * Author: Michael Onken + * + * Purpose: Class representing a Enhanced CT object + * + */ +#include "dcmtk/dcmect/enhanced_ct.h" +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmect/types.h" +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmiod/modimagepixel.h" + +struct EctEnhancedCT::SetImagePixelModuleVisitor +{ + SetImagePixelModuleVisitor(const Uint16 r, const Uint16 c) + : rows(r) + , cols(c) + { + } + + template + OFCondition operator()(T& t) + { + if ((rows == 0) || (cols == 0)) + { + DCMECT_ERROR("Rows/Cols must be non-zero but are : " << rows << "/" << cols); + return ECT_InvalidDimensions; + } + + t.setRows(rows); + t.setColumns(cols); + t.setBitsAllocated(16); + t.setBitsStored(16); + t.setHighBit(15); + t.setSamplesPerPixel(1); + t.setPhotometricInterpretation("MONOCHROME2"); + t.setPixelRepresentation(OFis_signed::value ? 1 : 0); + + return EC_Normal; + } + + // Members + const Uint16 rows; + const Uint16 cols; +}; + +// ---------------------------------------------------------------------------- +// Class WriteVisitor: +// Class for adding DICOM pixel data bulk element based on type pixel data type +// ---------------------------------------------------------------------------- + +// Generic implementation, template specialization is done in inner +// DcmElementOf class +struct EctEnhancedCT::WriteVisitor +{ + // Inner class that implements the specializations for different + // pixel data types + // template class DcmElementOf; + + // Constructor, sets parameters the visitor works on in operator() + WriteVisitor(DcmItem& i, EctEnhancedCT& m) + : m_Item(i) + , m_CT(m) + { + // Nothing else to do + } + + // + OFCondition operator()(OFmonostate) + { + DCMECT_ERROR("Could not write pixel data: Invalid pixel data type, only 16 bit integer is handled"); + return ECT_NoPixelData; + } + + template + OFCondition operator()(ImagePixel& pixel) + { + // Avoid compiler warning about unused parameter "pixel" + (void)pixel; + // Input data is checked before + Uint16 rows = 0; + Uint16 cols = 0; + m_CT.getRows(rows); + m_CT.getColumns(cols); + const size_t numFrames = m_CT.m_Frames.size(); + const size_t numBytesFrame = m_CT.m_Frames[0]->length; + const size_t numPixelsFrame = rows * cols; + // Creates the correct pixel data element, based on the image pixel module used. + DcmPixelData* pixData = new DcmPixelData(DCM_PixelData); + OFCondition result; + if (pixData) + { + pixData->setVR(EVR_OW); + Uint16* ptr = NULL; + size_t numBytesTotal = numBytesFrame * numFrames / 2; + if (numBytesTotal <= 4294967294UL) + { + result = pixData->createUint16Array(OFstatic_cast(Uint32, numBytesTotal), ptr); + // copy all frames into CT's frame structure + if (ptr) + { + for (size_t f = 0; f < numFrames; ++f) + { + memcpy(ptr, m_CT.m_Frames[f]->pixData, numBytesFrame); + ptr += numPixelsFrame; + } + return m_Item.insert(pixData); + } + } + else + { + result = FG_EC_PixelDataTooLarge; + delete pixData; + } + } + return result; + } + + // Members, i.e. parameters to operator() + DcmItem& m_Item; + EctEnhancedCT& m_CT; +}; + +// Generic implementation, template specialization is done in inner +// DcmElementOf class +struct EctEnhancedCT::WriteVisitorConcatenation +{ + // Inner class that implements the writing to Concatentions via ConcatenationCreator class + + // Constructor, sets parameters the visitor works on in operator() + WriteVisitorConcatenation(EctEnhancedCT& m, Uint8*& pixData, size_t& pixDataLength) + : m_CT(m) + , m_pixData(pixData) + , m_pixDataLength(pixDataLength) + { + // Nothing else to do + } + + // + OFCondition operator()(OFmonostate) + { + DCMECT_ERROR("Could not write pixel data: Invalid pixel data type, only 16 bit integer is handled"); + return ECT_NoPixelData; + } + + template + OFCondition operator()(ImagePixel& pixel) + { + // Avoid compiler warning about unused parameter "pixel" + (void)pixel; + // Input data is checked before + Uint16 rows = 0; + Uint16 cols = 0; + m_CT.getRows(rows); + m_CT.getColumns(cols); + const size_t numFrames = m_CT.m_Frames.size(); + const size_t numBytesFrame = m_CT.m_Frames[0]->length; + // Creates the correct pixel data element, based on the image pixel module used. + m_pixDataLength = numBytesFrame * numFrames; + m_pixData = new Uint8[m_pixDataLength]; + if (m_pixData) + { + Uint8* ptr = m_pixData; + // copy all frames into CT's frame structure + if (ptr) + { + for (size_t f = 0; f < numFrames; ++f) + { + memcpy(ptr, m_CT.m_Frames[f]->pixData, numBytesFrame); + ptr += numBytesFrame; + } + return EC_Normal; + } + } + m_pixData = OFnullptr; + m_pixDataLength = 0; + return EC_MemoryExhausted; + } + + // Members, i.e. parameters to operator() + EctEnhancedCT& m_CT; + Uint8*& m_pixData; + size_t& m_pixDataLength; +}; + +struct EctEnhancedCT::ReadVisitor +{ + // Inner class that implements the specializations for different + // pixel data types + template + class DcmElementOf; + + ReadVisitor(DcmItem& srcItem, EctEnhancedCT& m, const OFBool readPixelData = OFTrue) + : m_Item(srcItem) + , m_CT(m) + , m_readPixelData(readPixelData) + { + // Nothing to do + } + + OFCondition operator()(OFmonostate) + { + return ECT_InvalidPixelData; + } + + template + OFCondition operator()(ImagePixel& pixel) + { + m_CT.readGeneric(m_Item); + OFCondition result; + Uint16 rows, cols; + Uint32 numFrames; + size_t numBytesFrame = 0; + rows = cols = 0; + m_CT.getRows(rows); + m_CT.getColumns(cols); + numFrames = DcmIODUtil::limitMaxFrames( + m_CT.getFunctionalGroups().getNumberOfFrames(), + "Functional groups implicate more than 2147483647 frames, only 2147483647 will be used"); + if (!rows || !cols || !numFrames) + { + DCMECT_ERROR("Rows (" << rows << "), Columns (" << cols << ") and Number of Frames (" << numFrames + << ") must not be 0"); + return ECT_InvalidPixelInfo; + } + numBytesFrame = OFstatic_cast(size_t, rows) * cols * sizeof(typename ImagePixel::value_type); + if (m_readPixelData) + { + result = readSpecific(pixel, numFrames, numBytesFrame); + } + return result; + } + + template + OFCondition readSpecific(IODImagePixelModule& p, const Uint32 numFrames, const size_t numBytesFrame) + { + // Avoid compiler warning about unused parameter + (void)p; + unsigned long numTotalWords = 0; + const Uint16* pixData = NULL; + if (m_Item.findAndGetUint16Array(DCM_PixelData, pixData, &numTotalWords).good()) + { + if (numTotalWords == numBytesFrame * numFrames / 2 /* we compare to num words not num bytes */) + { + for (Uint32 n = 0; n < numFrames; n++) + { + DcmIODTypes::Frame* f = new DcmIODTypes::Frame; + if (f) + { + f->length = numBytesFrame; + f->pixData = new Uint8[f->length]; + memcpy(f->pixData, pixData + n * numBytesFrame / 2, numBytesFrame); + m_CT.m_Frames.push_back(f); + } + else + { + return EC_MemoryExhausted; + } + } + } + else + { + DCMECT_ERROR("Invalid number of pixels: Expected " << numBytesFrame * numFrames / 2 + << " pixels but Pixel Data has " << numTotalWords + << " pixels"); + return ECT_InvalidPixelInfo; + } + } + else + { + DCMECT_ERROR("No Pixel Data element found"); + return ECT_NoPixelData; + } + return EC_Normal; + } + + // Members, i.e. parameters to operator() + DcmItem& m_Item; + EctEnhancedCT& m_CT; + OFBool m_readPixelData; +}; + +template +EctEnhancedCT::Frames::Frames(EctEnhancedCT& ct) + : m_CT(ct) +{ +} + +template +OFCondition EctEnhancedCT::Frames::addFrame(PixelType* data, + const size_t numPixels, + const OFVector& perFrameInformation) +{ + OFCondition result; + if (data && numPixels) + { + if (!perFrameInformation.empty()) + { + OFunique_ptr f(new DcmIODTypes::Frame); + if (f) + { + f->length = numPixels * sizeof(PixelType); + f->pixData = new Uint8[f->length]; + memcpy(f->pixData, data, f->length); + m_CT.m_Frames.push_back(f.release()); + OFVector::const_iterator fg = perFrameInformation.begin(); + while (result.good() && (fg != perFrameInformation.end())) + { + result = m_CT.m_FGInterface.addPerFrame(OFstatic_cast(Uint32, m_CT.m_Frames.size()), **fg); + if (result.bad()) + { + DCMECT_ERROR( + "Could not add functional group: " << DcmFGTypes::FGType2OFString((*fg)->getType())); + break; + } + ++fg; + } + } + } + } + // Clean up if necessary + if (result.bad()) + m_CT.m_FGInterface.deleteFrame(OFstatic_cast(Uint32, m_CT.m_Frames.size())); + return result; +} + +template +PixelType* EctEnhancedCT::Frames::getFrame(const size_t frameNumber) +{ + if (frameNumber < m_CT.m_Frames.size()) + { + return (PixelType*)(m_CT.m_Frames[frameNumber]->pixData); + } + return NULL; +} + +// Helper "class" that returns Frames offering API to the pixel's frame bulk +// data by offering the dedicated data type, e.g. Float32 instead of the +// internally stored generic Uint8 array. +// +struct EctEnhancedCT::GetFramesVisitor +{ + GetFramesVisitor(EctEnhancedCT& ct) + : m_CT(ct) + { + } + + OFCondition operator()(OFmonostate) + { + return ECT_InvalidPixelData; + } + + template + Frames operator()(ImagePixel&) + { + return Frames(m_CT); + } + + EctEnhancedCT& m_CT; +}; + +// default constructor (protected, instance creation via create() function) +template +EctEnhancedCT::EctEnhancedCT(OFin_place_type_t(ImagePixel)) + : IODImage(OFin_place) + , m_SynchronisationModule() + , m_SynchronisationModuleEnabled(OFFalse) + , m_EnhancedGeneralEquipmentModule() + , m_FG() + , m_DimensionModule() + , m_AcquisitionContextModule() + , m_CommonInstanceReferenceModule() + , m_Frames() + , m_FGInterface() + , m_ImageType(DCM_ImageType) + , m_InstanceNumber(DCM_InstanceNumber) + , m_MultiEnergyCTAcquisition(DCM_MultienergyCTAcquisition) + , m_PixelPresentation(DCM_PixelPresentation) + , m_VolumetricProperties(DCM_VolumetricProperties) + , m_VolumeBasedCalculationTechnique(DCM_VolumeBasedCalculationTechnique) + , m_AcquisitionNumber(DCM_AcquisitionNumber) + , m_AcquisitionDateTime(DCM_AcquisitionDateTime) + , m_AcquisitionDuration(DCM_AcquisitionDuration) + , m_ContentQualification(DCM_ContentQualification) + , m_ImageComments(DCM_ImageComments) + , m_BurnedInAnnotation(DCM_BurnedInAnnotation) + , m_RecognizableVisualFeatures(DCM_RecognizableVisualFeatures) + , m_LossyImageCompression(DCM_LossyImageCompression) + , m_LossyImageCompressionRatio(DCM_LossyImageCompressionRatio) + , m_LossyImageCompressionMethod(DCM_LossyImageCompressionMethod) + , m_PresentationLUTShape(DCM_PresentationLUTShape) + , m_IsoCenterPosition(DCM_IsocenterPosition) +{ + setGeneralImageModuleEnabled(OFFalse); +} + +// ------------------ Constructors, Loading, Saving ----------------------- + +EctEnhancedCT::~EctEnhancedCT() +{ + DcmIODUtil::freeContainer(m_Frames); +} + +OFCondition EctEnhancedCT::loadFile(const OFString& filename, EctEnhancedCT*& ct) +{ + DcmFileFormat dcmff; + OFCondition cond = dcmff.loadFile(filename.c_str()); + if (cond.good()) + { + cond = loadDataset(*(dcmff.getDataset()), ct); + } + return cond; +} + +OFCondition EctEnhancedCT::loadDataset(DcmDataset& dataset, EctEnhancedCT*& ct) +{ + OFCondition result; + OFString sopClass; + if (dataset.findAndGetOFStringArray(DCM_SOPClassUID, sopClass).good()) + { + if (sopClass == UID_EnhancedCTImageStorage) + { + result = decompress(dataset); + if (result.good()) + { + + DcmElement* elem = NULL; + if (dataset.findAndGetElement(DCM_PixelData, elem).good()) + { + Uint16 pr = 0; + if (dataset.findAndGetUint16(DCM_PixelRepresentation, pr).good()) + { + if (pr == 0) + { + ct = new EctEnhancedCT(OFin_place >); + } + else + { + ct = new EctEnhancedCT(OFin_place >); + } + } + else + { + DCMECT_WARN("Pixel Data element found but no Pixel Presentation set, assuming 16 bit unsigned " + "integer data"); + ct = new EctEnhancedCT(OFin_place >); + } + } + else + { + return ECT_NoPixelData; + } + if (ct == NULL) + { + return EC_MemoryExhausted; + } + } + else + { + return result; + } + } + else + { + DCMECT_ERROR("Invalid SOP Class: " + << sopClass << ", only Enhanced CT Image Storage (1.2.840.10008.5.1.4.1.1.2.1​) supported"); + return ECT_InvalidSOPClass; + } + } + result = OFvisit(ReadVisitor(dataset, *ct), ct->getImagePixel()); + if (result.bad()) + { + delete ct; + ct = NULL; + } + return result; +} + +OFCondition +EctEnhancedCT::loadConcatenation(ConcatenationLoader& cl, const OFString& concatenationUID, EctEnhancedCT*& ct) +{ + + DcmDataset dset; + ct = NULL; + OFVector frames; + OFCondition result = cl.load(concatenationUID, &dset, frames); + if (result.good()) + { + Uint16 pr = 0; + if (dset.findAndGetUint16(DCM_PixelRepresentation, pr).good()) + { + if (pr == 0) + { + ct = new EctEnhancedCT(OFin_place >); + } + else + { + ct = new EctEnhancedCT(OFin_place >); + } + } + else + { + DCMECT_WARN("No Pixel Presentation set, assuming 16 bit unsigned " + "integer data"); + ct = new EctEnhancedCT(OFin_place >); + } + result + = OFvisit(ReadVisitor(dset, *ct, OFFalse /* do not read pixel data */), ct->getImagePixel()); + if (result.good()) + { + ct->m_Frames = frames; + } + if (result.bad()) + { + delete ct; + ct = NULL; + } + } + return result; +} + +OFCondition EctEnhancedCT::saveFile(const OFString& filename, const E_TransferSyntax writeXfer) +{ + DcmFileFormat dcmff; + OFCondition result; + if ((result = write(*dcmff.getDataset())).good()) + result = dcmff.saveFile(filename.c_str(), writeXfer); + if (result.bad()) + DCMECT_ERROR("Cannot save Enhanced CT object to file " << filename << ": " << result.text()); + return result; +} + +OFCondition EctEnhancedCT::writeDataset(DcmItem& dataset) +{ + return write(dataset); +} + +void EctEnhancedCT::setCheckFGOnWrite(const OFBool doCheck) +{ + m_FGInterface.setCheckOnWrite(doCheck); +} + +OFBool EctEnhancedCT::getCheckFGOnWrite() +{ + return m_FGInterface.getCheckOnWrite(); +} + +// ------------------ Creation ----------------------- + +OFCondition EctEnhancedCT::create(EctEnhancedCT*& ct, + const Uint16 rows, + const Uint16 columns, + const OFBool signedPixelData, + const EctTypes::E_ImageType1 imageType1, + const OFString& imageType3, + const OFString& imageType4, + const OFString& instanceNumber, + const EctTypes::E_ContentQualification contentQualification, + const EctTypes::E_PixelPresentation pixelPresentation, + const EctTypes::E_VolumetricProperties volumetricProperties, + const OFString& volumeBasedCalculationTechnique, + const IODEnhGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const OFString& acquisitionDateTime, + const Float64& acquisitionDuration) +{ + ct = OFnullptr; + OFCondition status; + if (!signedPixelData) + { + ct = new EctEnhancedCT(OFin_place >); + if (ct) + status + = SetImagePixelModuleVisitor(rows, columns)(*OFget >(&ct->getImagePixel())); + else + status = EC_MemoryExhausted; + } + else + { + ct = new EctEnhancedCT(OFin_place >); + if (ct) + status + = SetImagePixelModuleVisitor(rows, columns)(*OFget >(&ct->getImagePixel())); + else + status = EC_MemoryExhausted; + } + if (status.bad()) + return status; + + if (status.good()) + status = ct->getSOPCommon().setSOPClassUID(UID_EnhancedCTImageStorage); + + if (status.good()) + status = ct->setImageType(EctTypes::imageType1ToStr(imageType1) + "\\" + + EctTypes::imageType2ToStr(EctTypes::E_ImageType2_Primary) + "\\" + imageType3 + "\\" + + imageType4); + + if (status.good()) + status = ct->getIODMultiFrameFGModule().setInstanceNumber(instanceNumber); + if (status.good()) + status = ct->setContentQualification(contentQualification); + if (status.good()) + status = ct->setPixelPresentation(pixelPresentation); + if (status.good()) + status = ct->setVolumetricProperties(volumetricProperties); + if (status.good()) + status = ct->setVolumeBasedCalculationTechnique(volumeBasedCalculationTechnique); + if (status.good()) + status = ct->setLossyImageCompression(OFFalse); + if (status.good()) + status = ct->getIODEnhGeneralEquipmentModule().set(equipmentInfo); + if (status.good() && (!acquisitionDateTime.empty())) + status = ct->setAcquisitionDateTime(acquisitionDateTime); + if (status.good() && (acquisitionDuration >= 0)) + status = ct->setAcquisitionDuration(acquisitionDuration); + if (status.good()) + status = ct->m_BurnedInAnnotation.putOFStringArray("NO"); + + if (status.good()) + status = DcmIODUtil::setContentDateAndTimeNow(ct->getIODMultiFrameFGModule()); + + return status; +} + +// ------------------ Access ----------------------- + +OFBool EctEnhancedCT::check(const OFBool checkFGStructure) +{ + if (m_Frames.size() == 0) + { + DCMECT_ERROR("No frame data available"); + return OFFalse; + } + + if (checkFGStructure) + { + if (!m_FGInterface.check()) + return OFFalse; + } + + return OFTrue; +} + +FGInterface& EctEnhancedCT::getFunctionalGroups() +{ + return m_FGInterface; +} + +IODMultiFrameFGModule::ConcatenationInfo& EctEnhancedCT::getConcatenationInfo() +{ + return m_FG.getConcatenationInfo(); +} + +size_t EctEnhancedCT::getNumberOfFrames() const +{ + return OFconst_cast(EctEnhancedCT*, this)->m_FGInterface.getNumberOfFrames(); +} + +// ------------------ Access ----------------------- + +OFCondition EctEnhancedCT::addForAllFrames(const FGBase& group) +{ + return m_FGInterface.addShared(group); +} + +IODMultiframeDimensionModule& EctEnhancedCT::getDimensions() +{ + return m_DimensionModule; +} + +EctEnhancedCT::FramesType EctEnhancedCT::getFrames() +{ + return OFvisit(GetFramesVisitor(*this), getImagePixel()); +} + +OFCondition EctEnhancedCT::importFromSourceImage(DcmItem& dataset, const OFBool takeOverCharset) +{ + OFString FoR; + dataset.findAndGetOFString(DCM_FrameOfReferenceUID, FoR); + return IODImage::importHierarchy(dataset, + OFTrue, // Patient + OFTrue, // Study + !FoR.empty(), // Frame of Reference + OFFalse, // Series + takeOverCharset); +} + +OFCondition EctEnhancedCT::importFromSourceImage(const OFString& filename, const OFBool takeOverCharset) +{ + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(filename); + if (result.good()) + { + return importFromSourceImage(*(dcmff.getDataset()), takeOverCharset); + } + return result; +} + +// ------------------- Module getters / setters ------------------------- + +IODPatientModule& EctEnhancedCT::getIODPatientModule() +{ + return IODImage::getPatient(); +} + +IODPatientStudyModule& EctEnhancedCT::getIODPatientStudyModule() +{ + return IODImage::getPatientStudy(); +} + +IODGeneralStudyModule& EctEnhancedCT::getIODGeneralStudyModule() +{ + return IODImage::getStudy(); +} + +IODGeneralSeriesModule& EctEnhancedCT::getIODGeneralSeriesModule() +{ + return IODImage::getSeries(); +} + +IODFoRModule& EctEnhancedCT::getIODFrameOfReferenceModule() +{ + return IODImage::getFrameOfReference(); +} + +IODSynchronizationModule& EctEnhancedCT::getIODSynchronizationModule() +{ + return m_SynchronisationModule; +} + +void EctEnhancedCT::setIODSynchronisationModuleEnabled(const OFBool enabled) +{ + m_SynchronisationModuleEnabled = enabled; +} + +OFBool EctEnhancedCT::getIODSynchronisationModuleEnabled() +{ + return m_SynchronisationModuleEnabled; +} + +IODGeneralEquipmentModule& EctEnhancedCT::getIODGeneralEquipmentModule() +{ + return IODImage::getEquipment(); +} + +IODEnhGeneralEquipmentModule& EctEnhancedCT::getIODEnhGeneralEquipmentModule() +{ + return m_EnhancedGeneralEquipmentModule; +} + +IODMultiFrameFGModule& EctEnhancedCT::getIODMultiFrameFGModule() +{ + return m_FG; +} + +IODMultiframeDimensionModule& EctEnhancedCT::getIODMultiframeDimensionModule() +{ + return m_DimensionModule; +} + +IODAcquisitionContextModule& EctEnhancedCT::getIODAcquisitionContextModule() +{ + return m_AcquisitionContextModule; +} + +IODSOPCommonModule& EctEnhancedCT::getIODSOPCommonModule() +{ + return IODImage::getSOPCommon(); +} + +IODCommonInstanceReferenceModule& EctEnhancedCT::getIODCommonInstanceReferenceModule() +{ + return m_CommonInstanceReferenceModule; +} + +// --------- Getters from Image Pixel, Enhanced CT Series, as far as applicable --------------- + +OFCondition EctEnhancedCT::getImageType(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getAcquisitionNumber(Sint32& value, const unsigned long pos) +{ + return getData()->findAndGetSint32(DCM_AcquisitionNumber, value, pos); +} + +OFCondition EctEnhancedCT::getAcquisitionNumber(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionNumber, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getAcquisitionDateTime(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getAcquisitionDuration(Float64& value, const unsigned long pos) +{ + return getData()->findAndGetFloat64(DCM_AcquisitionDuration, value, pos); +} + +OFCondition EctEnhancedCT::getAcquisitionDuration(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDuration, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getContentQualification(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentQualification, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getImageComments(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ImageComments, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getBurnedInAnnotation(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getRecognizableVisualFeatures(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getLossyImageCompression(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getLossyImageCompressionRatio(Float64& value, const unsigned long pos) +{ + return getData()->findAndGetFloat64(DCM_LossyImageCompressionRatio, value, pos); +} + +OFCondition EctEnhancedCT::getLossyImageCompressionRatio(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionRatio, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getLossyImageCompressionMethod(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getPresentationLUTShape(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getMultiEnergyCTAcquisition(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_MultienergyCTAcquisition, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getPixelPresentation(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PixelPresentation, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getVolumetricProperties(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_VolumetricProperties, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getVolumeBasedCalculationTechnique(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_VolumeBasedCalculationTechnique, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getIsocenterPosition(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_IsocenterPosition, *getData(), value, pos); +} + +OFCondition EctEnhancedCT::getIsocenterPosition(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromItem(DCM_IsocenterPosition, *getData(), values); +} + +OFCondition EctEnhancedCT::getColumns(Uint16& cols) +{ + return getImagePixel().getColumns(cols); +} + +OFCondition EctEnhancedCT::getRows(Uint16& rows) +{ + return getImagePixel().getRows(rows); +} + +// --------- Setters from Image Pixel, Enhanced CT Series, as far as applicable --------------- + +OFCondition EctEnhancedCT::setImageType(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmCodeString::checkStringValue(value, "4") : EC_Normal; + if (result.good()) + result = m_ImageType.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setAcquisitionNumber(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AcquisitionNumber.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setAcquisitionDateTime(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AcquisitionDateTime.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setAcquisitionDuration(const Float64& value, const bool check) +{ + (void)check; + return m_AcquisitionDuration.putFloat64(value); +} + +OFCondition EctEnhancedCT::setContentQualification(const EctTypes::E_ContentQualification value, const OFBool check) +{ + (void)check; + if ((value == EctTypes::E_ContentQuali_Invalid) || (value == EctTypes::E_ContentQuali_Empty)) + return ECT_InvalidAttributeValue; + + return m_ContentQualification.putOFStringArray(EctTypes::contentQualiToStr(value)); +} + +OFCondition EctEnhancedCT::setImageComments(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmLongText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ImageComments.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setRecognizableVisualFeatures(const EctTypes::E_RecognizableVisualFeatures value, + const OFBool check) +{ + (void)check; + if ((value == EctTypes::E_RecoVisFeatures_Invalid) || (value == EctTypes::E_RecoVisFeatures_Empty)) + return ECT_InvalidAttributeValue; + + return m_RecognizableVisualFeatures.putOFStringArray(EctTypes::recoVisFeaturesToStr(value)); +} + +OFCondition EctEnhancedCT::setLossyImageCompression(const OFBool isLossy, + const OFString& ratios, + const OFString& methods, + const OFBool check) +{ + if (!isLossy) + { + return m_LossyImageCompression.putOFStringArray("00"); + } + + OFCondition result = m_LossyImageCompression.putOFStringArray("01"); + if (result.good()) + result = (check) ? DcmDecimalString::checkStringValue(ratios, "1-n") : EC_Normal; + if (result.good()) + result = m_LossyImageCompression.putOFStringArray(ratios); + + if (result.good()) + result = (check) ? DcmCodeString::checkStringValue(methods, "1-n") : EC_Normal; + if (result.good()) + result = m_LossyImageCompressionMethod.putOFStringArray(methods); + + return result; +} + +OFCondition EctEnhancedCT::setISOCenterPosition(const OFVector& values, const OFBool check) +{ + return DcmIODUtil::setFloat64ValuesOnElement(m_IsoCenterPosition, values, "3", check); +} + +OFCondition EctEnhancedCT::setISOCenterPosition(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmDecimalString::checkStringValue(value, "3") : EC_Normal; + if (result.good()) + result = m_IsoCenterPosition.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setMultiEnergyCTAcquisition(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_MultiEnergyCTAcquisition.putOFStringArray(value); + return result; +} + +OFCondition EctEnhancedCT::setPixelPresentation(const EctTypes::E_PixelPresentation value, const OFBool check) +{ + (void)check; + if ((value == EctTypes::E_PixelPres_Empty) || (value == EctTypes::E_PixelPres_Invalid)) + return ECT_InvalidAttributeValue; + + return m_PixelPresentation.putOFStringArray(EctTypes::pixelPresToStr(value)); +} + +OFCondition EctEnhancedCT::setVolumetricProperties(const EctTypes::E_VolumetricProperties value, const OFBool check) +{ + (void)check; + if ((value == EctTypes::E_VolProps_Empty) || (value == EctTypes::E_VolProps_Invalid)) + return ECT_InvalidAttributeValue; + + return m_VolumetricProperties.putOFStringArray(EctTypes::volPropsToStr(value)); +} + +OFCondition EctEnhancedCT::setVolumeBasedCalculationTechnique(const OFString& value, const OFBool check) +{ + OFCondition result = (check) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VolumeBasedCalculationTechnique.putOFStringArray(value); + return result; +} + +// -------------------- Protected Helpers -------------------------- + +OFCondition EctEnhancedCT::read(DcmItem& dataset) +{ + OFCondition result = OFvisit(ReadVisitor(dataset, *this), getImagePixel()); + return result; +} + +OFCondition EctEnhancedCT::write(DcmItem& dataset) +{ + if (!check()) + { + return IOD_EC_InvalidObject; + } + + OFCondition result = OFvisit(WriteVisitor(dataset, *this), getImagePixel()); + if (result.good()) + result = writeGeneric(dataset); + return result; +} + +OFCondition EctEnhancedCT::writeConcatenation(ConcatenationCreator& cc) +{ + if (!check()) + { + return IOD_EC_InvalidObject; + } + + DcmItem* item = new DcmItem(); + if (!item) + return EC_MemoryExhausted; + + Uint8* pixData = NULL; + size_t pixDataLength = 0; + + OFCondition result + = OFvisit(WriteVisitorConcatenation(*this, pixData, pixDataLength), getImagePixel()); + + if (result.good()) + result = writeGeneric(*item); + if (result.good()) + { + result = cc.setCfgInput(item, pixData, pixDataLength, OFTrue /* cc should take ownership */); + } + return result; +} + +OFCondition EctEnhancedCT::writeGeneric(DcmItem& dataset) +{ + OFCondition result; + if (m_SynchronisationModuleEnabled) + result = m_SynchronisationModule.write(dataset); + if (result.good()) + result = m_FG.setNumberOfFrames( + DcmIODUtil::limitMaxFrames(m_Frames.size(), "Maximum number of frames exceeded, will write 2147483647")); + if (result.good()) + result = m_FG.write(dataset); + if (result.good()) + result = m_FGInterface.write(dataset); + if (result.good()) + result = m_DimensionModule.write(dataset); + if (result.good()) + result = m_AcquisitionContextModule.write(dataset); + if (result.good()) + result = m_CommonInstanceReferenceModule.write(dataset); + if (result.good()) + result = getIODGeneralSeriesModule().setModality("CT"); + if (result.good()) + result = IODImage::write(dataset); + // Write after General Equipment Module from IODImage + if (result.good()) + result = m_EnhancedGeneralEquipmentModule.write(dataset); + + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_ImageType, "4" /* vm */, "1" /*requirement type*/, "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_MultiEnergyCTAcquisition, "1", "3", "EnhancedCTImageModule"); + if (result.good()) + result + = DcmIODUtil::copyElementToDataset(result, dataset, m_PixelPresentation, "1", "1", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_VolumetricProperties, "1", "1", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_VolumeBasedCalculationTechnique, "1", "1", "EnhancedCTImageModule"); + if (result.good()) + result + = DcmIODUtil::copyElementToDataset(result, dataset, m_AcquisitionNumber, "1", "3", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_AcquisitionDateTime, "1", "1C", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_AcquisitionDuration, "1", "1C", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_ContentQualification, "1", "1C", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset(result, dataset, m_ImageComments, "1", "3", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_BurnedInAnnotation, "1", "1C", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_RecognizableVisualFeatures, "1", "3", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_LossyImageCompression, "1", "1", "EnhancedCTImageModule"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_LossyImageCompressionMethod, "1-n", "1C", "EnhancedCTImageModule"); + + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_LossyImageCompressionRatio, "1-n", "1C", "EnhancedCTImageModule"); + + m_PresentationLUTShape.putOFStringArray("IDENTITY"); + if (result.good()) + result = DcmIODUtil::copyElementToDataset( + result, dataset, m_PresentationLUTShape, "1", "1", "EnhancedCTImageModule"); + if (result.good()) + result + = DcmIODUtil::copyElementToDataset(result, dataset, m_IsoCenterPosition, "3", "3", "EnhancedCTImageModule"); + return result; +} + +OFCondition EctEnhancedCT::readGeneric(DcmItem& dataset) +{ + OFString sopClass; + if (DcmIODUtil::checkSOPClass(&dataset, UID_EnhancedCTImageStorage, sopClass).bad()) + { + DCMECT_ERROR("Given file does not seem to be a Enhanced CT storage object since SOP class is: " << sopClass); + return IOD_EC_WrongSOPClass; + } + + IODImage::read(dataset); + m_SynchronisationModule.read(dataset); + m_EnhancedGeneralEquipmentModule.read(dataset); + m_FG.read(dataset); + m_DimensionModule.read(dataset); + m_AcquisitionContextModule.read(dataset); + m_CommonInstanceReferenceModule.read(dataset); + m_FGInterface.read(dataset); + + // Enhanced CT Image Module + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_ImageType, "4", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_MultiEnergyCTAcquisition, "1", "3", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_PixelPresentation, "1", "1", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_VolumetricProperties, "1", "1", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset( + dataset, m_VolumeBasedCalculationTechnique, "1", "1", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_AcquisitionNumber, "1", "3", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_AcquisitionDateTime, "1", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_AcquisitionDuration, "1", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_ContentQualification, "1", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_BurnedInAnnotation, "1", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_RecognizableVisualFeatures, "1", "3", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_LossyImageCompression, "1", "1", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset( + dataset, m_LossyImageCompressionMethod, "1-n", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset( + dataset, m_LossyImageCompressionRatio, "1-n", "1C", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_PresentationLUTShape, "1", "1", "EnhancedCTImageModule"); + DcmIODUtil::getAndCheckElementFromDataset(dataset, m_IsoCenterPosition, "3", "3", "EnhancedCTImageModule"); + return EC_Normal; +} + +OFCondition EctEnhancedCT::decompress(DcmDataset& dset) +{ + DcmXfer xfer = dset.getOriginalXfer(); + OFCondition result; + // If the original transfer is encapsulated and we do not already have an uncompressed version, decompress or reject + // the file + if (xfer.isEncapsulated()) + { + DCMECT_DEBUG("Enhanced CT object is compressed, converting to uncompressed transfer syntax first"); + result = DcmIODUtil::decompress(dset); + } + return result; +} + +// Instantiate Frames template with both possible pixel data types +template class EctEnhancedCT::Frames; +template class EctEnhancedCT::Frames; diff --git a/dcmect/libsrc/types.cc b/dcmect/libsrc/types.cc new file mode 100644 index 00000000..2a2741ad --- /dev/null +++ b/dcmect/libsrc/types.cc @@ -0,0 +1,248 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * + * + * Author: Michael Onken + * + * Purpose: Class for managing common Enhanced CT-specific types + * + */ + +#include "dcmtk/dcmect/types.h" +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcerror.h" + +OFLogger DCM_dcmectLogger = OFLog::getLogger("dcmtk.dcmect"); + +/*---------------------------------* + * constant definitions + *---------------------------------*/ + +// conditions +// makeOFConditionConst(ECT_EC_...., OFM_dcmect, 1, OF_error, "..."); + +const OFString EctTypes::DT_ImageType3_Angio = "ANGIO"; +const OFString EctTypes::DT_ImageType3_Cardiac = "CARDICAC"; +const OFString EctTypes::DT_ImageType3_CardiacGated = "CARDIAC_GATED"; +const OFString EctTypes::DT_ImageType3_CardRespGated = "CARDRESP_GATED"; +const OFString EctTypes::DT_ImageType3_Dynamic = "DYNAMIC"; +const OFString EctTypes::DT_ImageType3_Fluoroscopy = "FLOUROSCOPY"; +const OFString EctTypes::DT_ImageType3_Localizer = "LOCALIZER"; +const OFString EctTypes::DT_ImageType3_Motion = "MOTION"; +const OFString EctTypes::DT_ImageType3_Perfusion = "PERFUSION"; +const OFString EctTypes::DT_ImageType3_PreContrast = "PRE_CONTRAST"; +const OFString EctTypes::DT_ImageType3_PostContrast = "POST_CONTRAST"; +const OFString EctTypes::DT_ImageType3_RespGated = "RESP_GATED"; +const OFString EctTypes::DT_ImageType3_Rest = "REST"; +const OFString EctTypes::DT_ImageType3_Static = "STATIC"; +const OFString EctTypes::DT_ImageType3_Stress = "STRESS"; +const OFString EctTypes::DT_ImageType3_Volume = "VOLUME"; +const OFString EctTypes::DT_ImageType3_NonParallel = "NON_PARALLEL"; +const OFString EctTypes::DT_ImageType3_WholeBody = "WHOLE_BODY"; + +const OFString EctTypes::DT_ImageType4_Addition = "ADDITION"; +const OFString EctTypes::DT_ImageType4_Division = "DIVISION"; +const OFString EctTypes::DT_ImageType4_Masked = "MASKED"; +const OFString EctTypes::DT_ImageType4_Maximum = "MAXIMUM"; +const OFString EctTypes::DT_ImageType4_Mean = "MEAN"; +const OFString EctTypes::DT_ImageType4_Minimum = "MINIMUM"; +const OFString EctTypes::DT_ImageType4_Multiplication = "MULTIPLICATION"; +const OFString EctTypes::DT_ImageType4_Resampled = "RESAMPLED"; +const OFString EctTypes::DT_ImageType4_Std_Deviation = "STD_DEVIATION"; +const OFString EctTypes::DT_ImageType4_Subtraction = "SUBTRACTION"; +const OFString EctTypes::DT_ImageType4_None = "NONE"; +const OFString EctTypes::DT_ImageType4_Quantity = "QUANTITY"; +const OFString EctTypes::DT_ImageType4_Mixed = "MIXED"; + +const OFString EctTypes::DT_VolBasedCalcTechnique_MaxIp = "MAX_IP"; +const OFString EctTypes::DT_VolBasedCalcTechnique_MinIp = "MIN_IP"; +const OFString EctTypes::DT_VolBasedCalcTechnique_VolumeRender = "VOLUME_RENDER"; +const OFString EctTypes::DT_VolBasedCalcTechnique_SurfaceRender = "SURFACE_RENDER"; +const OFString EctTypes::DT_VolBasedCalcTechnique_Mpr = "MPR"; +const OFString EctTypes::DT_VolBasedCalcTechnique_CurvedMpr = "CURVED_MPR"; +const OFString EctTypes::DT_VolBasedCalcTechnique_None = "NONE"; +const OFString EctTypes::DT_VolBasedCalcTechnique_Mixed = "MIXED"; + +// conditions +makeOFConditionConst(ECT_InvalidDimensions, OFM_dcmect, 1, OF_error, "Invalid Dimensions"); +makeOFConditionConst(ECT_InvalidAttributeValue, OFM_dcmect, 2, OF_error, "Invalid Attribute Value"); +makeOFConditionConst( + ECT_InvalidPixelInfo, OFM_dcmect, 3, OF_error, "Invalid information in pixel data or related attributes"); +makeOFConditionConst(ECT_InvalidPixelData, OFM_dcmect, 4, OF_error, "Invalid pixel data"); +makeOFConditionConst(ECT_NoPixelData, OFM_dcmect, 5, OF_error, "No pixel data found"); +makeOFConditionConst(ECT_InvalidSOPClass, OFM_dcmect, 6, OF_error, "SOP Class not supported"); + +OFString EctTypes::imageType1ToStr(const E_ImageType1 value) +{ + switch (value) + { + case E_ImageType1_Empty: + return ""; + break; + case E_ImageType1_Invalid: + return ""; + break; + case E_ImageType1_Original: + return "ORIGINAL"; + break; + case E_ImageType1_Derived: + return "DERIVED"; + break; + case E_ImageType1_Mixed: + return "MIXED"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_ImageType1: " << value); + return ""; + } +} + +OFString EctTypes::imageType2ToStr(const E_ImageType2 value) +{ + switch (value) + { + case E_ImageType2_Empty: + return ""; + break; + case E_ImageType2_Invalid: + return ""; + break; + case E_ImageType2_Primary: + return "PRIMARY"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_ImageType2: " << value); + return ""; + } +} + +OFString EctTypes::contentQualiToStr(const E_ContentQualification value) +{ + switch (value) + { + case E_ContentQuali_Empty: + return ""; + break; + case E_ContentQuali_Invalid: + return ""; + break; + case E_ContQuali_Product: + return "PRODUCT"; + break; + case E_ContQuali_Research: + return "RESEARCH"; + break; + case E_ContQuali_Service: + return "SERVICE"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_ContentQualification: " << value); + return ""; + } +} + +OFString EctTypes::burnedAnnoToStr(const E_BurnedInAnnotation value) +{ + switch (value) + { + case E_BurnedInAnno_Empty: + return ""; + break; + case E_BurnedInAnno_Invalid: + return ""; + break; + case E_BurnedInAnno_No: + return "NO"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_BurnedInAnnotation: " << value); + return ""; + } +} + +OFString EctTypes::pixelPresToStr(const E_PixelPresentation value) +{ + switch (value) + { + case E_PixelPres_Empty: + return ""; + break; + case E_PixelPres_Invalid: + return ""; + break; + case E_PixelPres_Color: + return "COLOR"; + break; + case E_PixelPres_Mixed: + return "MIXED"; + break; + case E_PixelPres_Monochrome: + return "MONOCHROME"; + case E_PixelPres_TrueColor: + return "TRUE_COLOR"; + default: + DCMECT_ERROR("Internal error, invalid value for E_PixelPresentation: " << value); + return ""; + } +} + +OFString EctTypes::volPropsToStr(const E_VolumetricProperties value) +{ + switch (value) + { + case E_VolProps_Empty: + return ""; + break; + case E_VolProps_Invalid: + return ""; + break; + case E_VolProps_Distorted: + return "DISTORTED"; + break; + case E_VolProps_Mixed: + return "MIXED"; + break; + case E_VolProps_Sampled: + return "SAMPLED"; + break; + case E_VolProps_Volume: + return "VOLUME"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_VolumetricProperties: " << value); + return ""; + } +} + +OFString EctTypes::recoVisFeaturesToStr(const E_RecognizableVisualFeatures value) +{ + switch (value) + { + case E_RecoVisFeatures_Empty: + return ""; + break; + case E_RecoVisFeatures_Invalid: + return ""; + break; + case E_RecoVisFeatures_No: + return "NO"; + break; + case E_RecoVisFeatures_Yes: + return "YES"; + break; + default: + DCMECT_ERROR("Internal error, invalid value for E_RecognizableVisualFeatures: " << value); + return ""; + } +} diff --git a/dcmect/tests/CMakeLists.txt b/dcmect/tests/CMakeLists.txt new file mode 100644 index 00000000..01e732de --- /dev/null +++ b/dcmect/tests/CMakeLists.txt @@ -0,0 +1,11 @@ +# declare executables +DCMTK_ADD_EXECUTABLE(dcmect_tests + tests + t_huge_concat + t_roundtrip) + +# make sure executables are linked to the corresponding libraries +DCMTK_TARGET_LINK_MODULES(dcmect_tests dcmect dcmfg dcmdata oflog ofstd) + +# This macro parses tests.cc and registers all tests +DCMTK_ADD_TESTS(dcmect) diff --git a/dcmect/tests/Makefile.dep b/dcmect/tests/Makefile.dep new file mode 100644 index 00000000..ba8cdd44 --- /dev/null +++ b/dcmect/tests/Makefile.dep @@ -0,0 +1,437 @@ +t_huge_concat.o: t_huge_concat.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofstrutl.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftempf.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmect/enhanced_ct.h ../include/dcmtk/dcmect/def.h \ + ../include/dcmtk/dcmect/types.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \ + ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsynchronisation.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctexposure.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctgeometry.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctposition.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgframevoilut.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h +t_roundtrip.o: t_roundtrip.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofstrutl.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftempf.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmect/enhanced_ct.h ../include/dcmtk/dcmect/def.h \ + ../include/dcmtk/dcmect/types.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \ + ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsynchronisation.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctexposure.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctgeometry.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctposition.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgframevoilut.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h +tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h diff --git a/dcmect/tests/Makefile.in b/dcmect/tests/Makefile.in new file mode 100644 index 00000000..78b6ae5c --- /dev/null +++ b/dcmect/tests/Makefile.in @@ -0,0 +1,59 @@ +# +# Makefile for dcmect/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmioddir = $(top_srcdir)/../dcmiod +dcmfgdir = $(top_srcdir)/../dcmfg + +LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ + -L$(dcmdatadir)/libsrc -L$(dcmioddir)/libsrc -L$(dcmfgdir)/libsrc +LOCALLIBS = -ldcmect -ldcmfg -ldcmiod -ldcmdata -loflog -lofstd $(ZLIBLIBS) \ + $(CHARCONVLIBS) $(MATHLIBS) +LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include \ + -I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include + +test_objs = tests.o t_huge_concat.o t_roundtrip.o +objs = $(test_objs) +progs = tests + + +all: $(progs) + +tests: $(test_objs) + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) $(LOCALINCLUDES) -o $@ $(test_objs) $(LOCALLIBS) $(LIBS) + + +check: tests + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests + +check-exhaustive: tests + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests -x + + +install: all + + +clean: + rm -f $(objs) $(progs) $(LOCALTRASH) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(LOCALTRASH) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmect/tests/t_huge_concat.cc b/dcmect/tests/t_huge_concat.cc new file mode 100644 index 00000000..c96b2fa5 --- /dev/null +++ b/dcmect/tests/t_huge_concat.cc @@ -0,0 +1,973 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Tests for creating huge (> 4 GB) Enhanced CT objects + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofstrutl.h" +#include "dcmtk/ofstd/oftempf.h" +#include "dcmtk/ofstd/oftest.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmect/enhanced_ct.h" + +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmfg/fgctacquisitiondetails.h" +#include "dcmtk/dcmfg/fgctacquisitiontype.h" +#include "dcmtk/dcmfg/fgctadditionalxraysource.h" +#include "dcmtk/dcmfg/fgctexposure.h" +#include "dcmtk/dcmfg/fgctgeometry.h" +#include "dcmtk/dcmfg/fgctimageframetype.h" +#include "dcmtk/dcmfg/fgctposition.h" +#include "dcmtk/dcmfg/fgctreconstruction.h" +#include "dcmtk/dcmfg/fgcttabledynamics.h" +#include "dcmtk/dcmfg/fgctxraydetails.h" +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgframeanatomy.h" +#include "dcmtk/dcmfg/fgframevoilut.h" +#include "dcmtk/dcmfg/fgirradiationeventid.h" +#include "dcmtk/dcmfg/fgpixeltransform.h" +#include "dcmtk/dcmfg/fgpixmsr.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" +#include "dcmtk/dcmfg/fgtemporalposition.h" + +static OFLogger tRoundLogger = OFLog::getLogger("dcmtk.test.t_huge_concat"); + +// Number of Rows of image, might be changed for testing purposes +static const Uint16 NUM_ROWS = 4000; +// Number of Columns of image, might be changed for testing purposes +static const Uint16 NUM_COLS = 4000; +// Number of Frames of source image, might be changed for testing purposes +static const Uint16 NUM_FRAMES = 200; +// Number of Frames of in concatenation images, should not be changed since the +// dumped checked against will assume Number of Frames = 1 +static const size_t NUM_FRAMES_CONCAT = 1; +static const size_t NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS; + +static const OFString CONCAT_SOP_INST_UID = "1.2.276.0.7230010.3.1.4.8323329.21580.1571390622.913190"; +static const OFString CONCATATENATION_UID = "1.2.276.0.7230010.3.1.4.8323329.23689.1571391649.103636"; + +static OFString EXPECTED_DUMP; + +static void prepareExpectedDump(); +static EctEnhancedCT* create(); +static void configureIOD(EctEnhancedCT* ct); +static void setGenericValues(EctEnhancedCT* ct); +static void addSharedFGs(EctEnhancedCT* ct); +static void addFrames(EctEnhancedCT* ct); +static void addDimensions(EctEnhancedCT* ct); +static void checkCreatedObject(const OFString& ds_dump); +static void writeAndCheckConcatenation(EctEnhancedCT* ct, OFList& concats); +static void checkConcatenationInstance(size_t numInstance, EctEnhancedCT* srcInstance, DcmDataset* concatInstance); +static void loadAndCheckConcatenation(const OFList& concats); + +OFTEST_FLAGS(dcmect_huge_concat, EF_Slow) +{ + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK(dcmDataDict.isDictionaryLoaded()); + return; + } + + // Creation + EctEnhancedCT* ct = create(); + configureIOD(ct); + setGenericValues(ct); + addSharedFGs(ct); + addFrames(ct); + addDimensions(ct); + + prepareExpectedDump(); + + OFList concats; + if (ct) + { + writeAndCheckConcatenation(ct, concats); + delete ct; + } + OFCHECK(!concats.empty()); + if (!concats.empty()) + { + loadAndCheckConcatenation(concats); + } + OFListIterator(OFFilename) it = concats.begin(); + while (it != concats.end()) + { + OFStandard::deleteFile(*it); + it++; + } +} + +static EctEnhancedCT* create() +{ + IODEnhGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1"); + EctEnhancedCT* ct = NULL; + OFCondition result; + result = EctEnhancedCT::create(ct, + NUM_ROWS, + NUM_COLS, + OFFalse, + EctTypes::E_ImageType1_Original, + EctTypes::DT_ImageType3_Volume, + EctTypes::DT_ImageType4_Maximum, + "1" /* instance number */, + EctTypes::E_ContQuali_Research, + EctTypes::E_PixelPres_Monochrome, + EctTypes::E_VolProps_Volume, + EctTypes::DT_VolBasedCalcTechnique_VolumeRender, + eq, + "20190801120000" /* acquisition date */, + 2.0 /* acquisition duration */); + + OFCHECK(result.good()); + OFCHECK(ct != OFnullptr); + return ct; +} + +static void configureIOD(EctEnhancedCT* ct) +{ + if (!ct) + return; +} + +static void setGenericValues(EctEnhancedCT* ct) +{ + if (!ct) + return; + OFCHECK(ct->getPatient().setPatientName("Bond^James").good()); + OFCHECK(ct->getPatient().setPatientID("007").good()); + OFCHECK(ct->getPatient().setPatientBirthDate("19771007").good()); + OFCHECK(ct->getStudy().setStudyDate("20190801").good()); + OFCHECK(ct->getStudy().setStudyTime("120000").good()); + OFCHECK(ct->getStudy().setStudyID("1").good()); + OFCHECK(ct->getPatientStudy().setPatientAge("040Y").good()); + OFCHECK(ct->getSeries().setSeriesDescription("Test Description").good()); + OFCHECK(ct->getSeries().setSeriesNumber("1").good()); + OFCHECK(ct->getSeries().setPatientPosition("HFS").good()); + + // Those values are usually computed automatically. UIDS are generated and date/times are set to current values. + // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually, + // so that they are not overwritten with new, automatically created values later. + OFCHECK(ct->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good()); + OFCHECK(ct->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good()); + OFCHECK(ct->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good()); + OFCHECK(ct->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good()); + + OFCHECK(ct->getIODMultiFrameFGModule().setContentTime("092557").good()); + OFCHECK(ct->getIODMultiFrameFGModule().setContentDate("20190816").good()); +} + +static void addSharedFGs(EctEnhancedCT* ct) +{ + if (!ct) + return; + + FGPixelMeasures meas; + OFCHECK(meas.setPixelSpacing("0.1\\0.1").good()); + OFCHECK(meas.setSliceThickness("1.0").good()); + OFCHECK(meas.setSpacingBetweenSlices("0.05").good()); + + FGPlanePosPatient planpo; + OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good()); + + FGPlaneOrientationPatient planor; + OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good()); + + FGFrameAnatomy ana; + OFCHECK(ana.setLaterality(FGFrameAnatomy::LATERALITY_BOTH).good()); + OFCHECK(ana.getAnatomy().getAnatomicRegion().set("12738006", "SCT", "Brain").good()); + + FGFrameVOILUT voi; + OFCHECK(voi.setCenterWidthExplanation(1000, 2000, FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_Brain).good()); + + FGIrradiationEventIdentification irr; + OFCHECK(irr.setIrradiationEventUID("2.25.30853892236613436472911970638347155062").good()); + + FGCTImageFrameType itype; + OFCHECK(itype.setFrameType("ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM").good()); + OFCHECK(itype.setPixelPresentation(FGCTImageFrameType::E_PixelPres_Monochrome).good()); + OFCHECK(itype.setVolumetricProperties(FGCTImageFrameType::E_VolProp_Volume).good()); + OFCHECK(itype.setVolumeBasedCalculationTechnique(FGCTImageFrameType::DT_VolBasedCalcTechnique_VolumeRender).good()); + + FGCTAcquisitionType atype; + OFCHECK(atype.setAcquisitionType(FGCTAcquisitionType::DT_AcquisitionType_ConstantAngle).good()); + OFCHECK(atype.setTubeAngle(0.1).good()); + OFCHECK(atype.setConstantVolumeFlag(FGCTAcquisitionType::E_ConstVol_Yes).good()); + OFCHECK(atype.setFluoroscopyFlag(FGCTAcquisitionType::E_Fluoroscopy_No).good()); + + FGCTAcquisitionDetails adetails; + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* item = new FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem(); + OFCHECK(item->setRotationDirection(FGCTAcquisitionDetails::E_RotationDirection_CW).good()); + OFCHECK(item->setRevolutionTime(5).good()); + OFCHECK(item->setSingleCollimationWidth(1).good()); + OFCHECK(item->setTotalCollimationWidth(10).good()); + OFCHECK(item->setTableHeight(50).good()); + OFCHECK(item->setGantryDetectorTilt(5).good()); + OFCHECK(item->setDataCollectionDiameter(20).good()); + adetails.getCTAcquisitionDetailsItems().push_back(item); + + FGCTTableDynamics dyn; + FGCTTableDynamics::FGCTTableDynamicsItem* dyn_item = new FGCTTableDynamics::FGCTTableDynamicsItem; + OFCHECK(dyn_item); + if (dyn_item) + { + OFCHECK(dyn_item->setTableSpeed(1.0).good()); + OFCHECK(dyn_item->setTableFeedPerRotation(0.1).good()); + OFCHECK(dyn_item->setSpiralPitchFactor(0.2).good()); + dyn.getCTTableDynamicsItems().push_back(dyn_item); + } + + FGCTPosition pos; + OFCHECK(pos.setTablePosition(100.0).good()); + OFCHECK(pos.setReconstructionTargetCenterPatient(OFVector(3, 1.0)).good()); + OFCHECK(pos.setDataCollectionCenterPatient(OFVector(3, 2.0)).good()); + + FGCTGeometry geo; + FGCTGeometry::FGCTGeometryItem* geo_item = new FGCTGeometry::FGCTGeometryItem; + if (geo_item) + { + OFCHECK(geo_item->setDistanceSourceToDataCollectionCenter(5.0).good()); + OFCHECK(geo_item->setDistanceSourceToDetector(0.5).good()); + geo.getCTGeometryItems().push_back(geo_item); + } + + FGCTReconstruction rec; + OFCHECK(rec.setConvolutionKernel("DUMMY").good()); + OFCHECK(rec.setConvolutionKernelGroup("DUMMYGROUP").good()); + OFCHECK(rec.setImageFilter("FILTER").good()); + OFCHECK(rec.setReconstructionAlgorithm("ALGO").good()); + OFCHECK(rec.setReconstructionAngle(90.0).good()); + OFCHECK(rec.setReconstructionDiameter(100.0).good()); + // Not permitted if Reconstruction Diameter is provided instead + // OFCHECK(rec.setReconstructionFieldOfView(100.0, 100.0).good()); + OFCHECK(rec.setReconstructionPixelSpacing(0.1, 0.1).good()); + + FGCTExposure exp; + FGCTExposure::FGCTExposureItem* exp_item = new FGCTExposure::FGCTExposureItem; + if (exp_item) + { + OFCHECK(exp_item->setCTDIVol(0.1).good()); + CodeSequenceMacro* phantom_item = new CodeSequenceMacro("113682", "DCM", "ACR Accreditation Phantom - CT"); + exp_item->getCTDIPhantomTypeCodeSequence().push_back(phantom_item); + OFCHECK(exp_item->setEstimatedDoseSaving(0.2).good()); + OFCHECK(exp_item->setExposureInMas(0.3).good()); + OFCHECK(exp_item->setExposureModulationType("WEIRD").good()); + OFCHECK(exp_item->setExposureTimeInMs(0.4).good()); + OFCHECK(exp_item->setImageAndFluoroscopyAreaDoseProduct(0.5).good()); + OFCHECK(exp_item->setWaterEquivalentDiameter(0.6).good()); + CodeSequenceMacro* water_code = new CodeSequenceMacro("113987", "DCM", "AAPM 220"); + exp_item->getWaterEquivalentDiameterCalculationMethodCodeSequence().push_back(water_code); + OFCHECK(exp_item->setXRayTubeCurrentInMa(0.7).good()); + exp.getCTExposureItems().push_back(exp_item); + } + + FGCTXRayDetails det; + FGCTXRayDetails::FGCTXRayDetailsItem* det_item = new FGCTXRayDetails::FGCTXRayDetailsItem; + if (det_item) + { + OFCHECK(det_item->setCalciumScoringMassFactorDevice(OFVector(3, 1)).good()); + OFCHECK(det_item->setCalciumScoringMassFactorPatient(2).good()); + OFCHECK(det_item->setEnergyWeightingFactor(3).good()); + OFCHECK(det_item->setFilterMaterial("FILTER_MATERIAL").good()); + OFCHECK(det_item->setFilterType("FILTER_TYPE").good()); + OFCHECK(det_item->setFocalSpots(OFVector(4, 4.4)).good()); + OFCHECK(det_item->setKVP(5.0).good()); + det.getCTXRayDetailsItems().push_back(det_item); + } + + FGPixelValueTransformation trans; + trans.setFGType(FGPixelValueTransformation::E_PixelValTrans_CT); + trans.setRescaleIntercept("0"); + trans.setRescaleSlope("1"); + trans.setRescaleType("HU"); + + FGCTAdditionalXRaySource asrc; + FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem* asrc_item + = new FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem; + if (asrc_item) + { + OFCHECK(asrc_item->setDataCollectionDiameter(1.0).good()); + OFCHECK(asrc_item->setEnergyWeightingFactor(2.0).good()); + OFCHECK(asrc_item->setExposureInmAs(3.0).good()); + OFCHECK(asrc_item->setFilterMaterial("FILTER_MATERIAL").good()); + OFCHECK(asrc_item->setFilterType("FILTER_TYPE").good()); + OFCHECK(asrc_item->setFocalSpots(OFVector(4, 4.4)).good()); + OFCHECK(asrc_item->setKVP(5).good()); + OFCHECK(asrc_item->setXRayTubeCurrentInmA(6).good()); + asrc.getCTAdditionalXRaySourceItems().push_back(asrc_item); + } + + FGTemporalPosition tempos; + OFCHECK(tempos.setTemporalPositionTimeOffset(1.0).good()); + + OFCHECK(ct->addForAllFrames(meas).good()); + OFCHECK(ct->addForAllFrames(planpo).good()); + OFCHECK(ct->addForAllFrames(planor).good()); + OFCHECK(ct->addForAllFrames(ana).good()); + OFCHECK(ct->addForAllFrames(voi).good()); + OFCHECK(ct->addForAllFrames(irr).good()); + OFCHECK(ct->addForAllFrames(itype).good()); + OFCHECK(ct->addForAllFrames(atype).good()); + OFCHECK(ct->addForAllFrames(adetails).good()); + OFCHECK(ct->addForAllFrames(dyn).good()); + OFCHECK(ct->addForAllFrames(pos).good()); + OFCHECK(ct->addForAllFrames(geo).good()); + OFCHECK(ct->addForAllFrames(rec).good()); + OFCHECK(ct->addForAllFrames(exp).good()); + OFCHECK(ct->addForAllFrames(det).good()); + OFCHECK(ct->addForAllFrames(trans).good()); + OFCHECK(ct->addForAllFrames(asrc).good()); + OFCHECK(ct->addForAllFrames(tempos).good()); +} + +static void addFrames(EctEnhancedCT* ct) +{ + if (!ct) + return; + + FGFrameContent* fg = new FGFrameContent(); + fg->setStackID("1"); + OFCHECK(fg); + if (fg) + { + EctEnhancedCT::FramesType frames = ct->getFrames(); + for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++) + { + OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good()); + OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDuration(0.001).good()); + OFCHECK(fg->setInStackPositionNumber(frameNo).good()); + OFCHECK(fg->setDimensionIndexValues(1, 0).good()); + OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good()); + OFVector groups; + groups.push_back(fg); + + Uint16* data = new Uint16[NUM_PIXELS_PER_FRAME]; + for (size_t i = 0; i < NUM_PIXELS_PER_FRAME; ++i) + { + data[i] = frameNo; + } + OFCHECK( + OFget >(&frames)->addFrame(data, NUM_PIXELS_PER_FRAME, groups).good()); + delete[] data; + } + } + delete fg; +} + +static void addDimensions(EctEnhancedCT* ct) +{ + if (!ct) + return; + IODMultiframeDimensionModule& dims = ct->getDimensions(); + OFCHECK(dims.addDimensionIndex( + DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM") + .good()); + OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber, + "2.25.30855560781715986879861690673941231222", + DCM_FrameContentSequence, + "STACK_DIM") + .good()); + OFunique_ptr org( + new IODMultiframeDimensionModule::DimensionOrganizationItem); + if (org) + { + org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222"); + dims.getDimensionOrganizationSequence().push_back(org.release()); + } +} + +static void writeAndCheckConcatenation(EctEnhancedCT* ct, OFList& concats) +{ + ConcatenationCreator cc; + cc.setCfgFramesPerInstance(NUM_FRAMES_CONCAT); + OFCHECK(ct->writeConcatenation(cc).good()); + size_t numInstances = cc.getNumInstances(); + OFCHECK(numInstances == NUM_FRAMES); + OFCondition result; + for (size_t n = 0; n < numInstances; n++) + { + OFStringStream s; + s << "concat_" << n << "_"; + OFTempFile tf(O_RDWR, "", s.str().c_str(), ".dcm"); + result = cc.writeNextInstance(tf.getFilename()); + OFCHECK(result.good()); + if (result.good()) + { + DcmFileFormat concat; + OFCHECK(concat.loadFile(tf.getFilename()).good()); + checkConcatenationInstance(n, ct, concat.getDataset()); + concats.push_back(tf.getFilename()); + tf.stealFile(); + } + } +} + +static void checkConcatenationInstance(size_t numInstance, EctEnhancedCT* srcInstance, DcmDataset* concatInstance) +{ + EctEnhancedCT* concat = NULL; + OFCondition result = EctEnhancedCT::loadDataset(*concatInstance, concat); + OFCHECK(result.good()); + if ((concat == NULL )|| result.bad()) return; + + size_t numFrames; + numFrames = concat->getNumberOfFrames(); + OFCHECK(numFrames == 1); + IODMultiFrameFGModule::ConcatenationInfo& ci = concat->getConcatenationInfo(); + OFString val; + OFCHECK(ci.getConcatenationUID(val).good()); + OFCHECK(DcmUniqueIdentifier::checkStringValue(val, "1").good()); + Uint32 frameOffsetNo = 0; + OFCHECK(ci.getConcatenationFrameOffsetNumber(frameOffsetNo).good()); + OFCHECK(frameOffsetNo == numInstance); + Uint16 inConcatNo = 0; + OFCHECK(ci.getInConcatenationNumber(inConcatNo).good()); + OFCHECK(inConcatNo == numInstance + 1); + Uint16 concatTotalNo = 0; + OFCHECK(ci.getInConcatenationTotalNumber(concatTotalNo).good()); + OFCHECK(concatTotalNo == NUM_FRAMES); + + OFString srcUID; + OFCHECK(ci.getSOPInstanceUIDOfConcatenationSource(srcUID).good()); + OFCHECK(srcInstance->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID == val); + + OFCHECK(concat->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID != val); + + FunctionalGroups::const_iterator srcShared = srcInstance->getFunctionalGroups().getShared()->begin(); + FunctionalGroups::const_iterator cShared = concat->getFunctionalGroups().getShared()->begin(); + size_t numShared = 0; + do + { + OFCHECK(srcShared->second->compare(*cShared->second) == 0); + srcShared++; + cShared++; + numShared++; + } while ((srcShared != srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared != concat->getFunctionalGroups().getShared()->end())); + OFCHECK((srcShared == srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared == concat->getFunctionalGroups().getShared()->end())); + DcmSequenceOfItems* cPerFrame = NULL; + result = concatInstance->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, cPerFrame); + OFCHECK(result.good()); + if ((cPerFrame == NULL) || result.bad()) return; + OFCHECK(cPerFrame->card() == 1); + + OFBool perFrame = OFFalse; + FGBase* fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTACQUISITIONDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTACQUISITIONTYPE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTADDITIONALXRAYSOURCE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTEXPOSURE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTGEOMETRY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTIMAGEFRAMETYPE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTPOSITION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTRECONSTRUCTION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTTABLEDYNAMICS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTXRAYDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTXRAYDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMECONTENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFTrue); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEVOILUTMETA, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_IRRADIATIONEVENTIDENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PIXELVALUETRANSMETA, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_IRRADIATIONEVENTIDENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PIXELMEASURES, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEPOSPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEORIENTPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_TEMPORALPOSITION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + EctEnhancedCT::FramesType frames = concat->getFrames(); + Uint16* frame = OFget >(&frames)->getFrame(0); + OFCHECK(frame != OFnullptr); + // Check that all pixels are set to their original source instances frame number (starting from 1) + for (size_t pix = 0; pix < NUM_PIXELS_PER_FRAME; pix++) + { + OFCHECK(frame[pix] == numInstance + 1); + } + delete concat; +} + +void loadAndCheckConcatenation(const OFList& concats) +{ + ConcatenationLoader cl; + OFCondition result = cl.scan(concats); + OFCHECK(result.good()); + if (result.good()) + { + DcmDataset merged; + EctEnhancedCT* mergedCT = NULL; + result = EctEnhancedCT::loadConcatenation(cl, cl.getInfo().begin()->first, mergedCT); + if (result.good()) + { + ConcatenationCreator cc; + cc.setCfgFramesPerInstance(1); + result = mergedCT->writeConcatenation(cc); + OFCHECK(result.good()); + if (result.good()) + { + DcmDataset d; + result = cc.writeNextInstance(d); + if (result.good()) + { + // patch in expected timestamp and instance UIDs to match dump + OFCHECK(d.putAndInsertOFStringArray(DCM_ContentDate, "20190816").good()); + OFCHECK(d.putAndInsertOFStringArray(DCM_ContentTime, "092557").good()); + OFCHECK(d.putAndInsertOFStringArray(DCM_SOPInstanceUID, + "1.2.276.0.7230010.3.1.4.8323329.21580.1571390622.913190") + .good()); + OFCHECK(d.putAndInsertOFStringArray(DCM_ConcatenationUID, + "1.2.276.0.7230010.3.1.4.8323329.23689.1571391649.103636") + .good()); + OFStringStream s; + d.print(s, DCMTypes::PF_shortenLongTagValues); + checkCreatedObject(s.str().c_str()); + checkConcatenationInstance(0, mergedCT, &d); + } + } + delete mergedCT; + } + } +} + +static void prepareExpectedDump() +{ + EXPECTED_DUMP += "\n"; + EXPECTED_DUMP += "# Dicom-Data-Set\n"; + EXPECTED_DUMP += "# Used TransferSyntax: Little Endian Explicit\n"; + EXPECTED_DUMP += "(0008,0008) CS [ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM] # 32, 4 ImageType\n"; + EXPECTED_DUMP += "(0008,0016) UI =EnhancedCTImageStorage # 28, 1 SOPClassUID\n"; + EXPECTED_DUMP + += "(0008,0018) UI [1.2.276.0.7230010.3.1.4.8323329.21580.1571390622.913190] # 56, 1 SOPInstanceUID\n"; + EXPECTED_DUMP += "(0008,0020) DA [20190801] # 8, 1 StudyDate\n"; + EXPECTED_DUMP += "(0008,0023) DA [20190816] # 8, 1 ContentDate\n"; + EXPECTED_DUMP += "(0008,002a) DT [20190801120000] # 14, 1 AcquisitionDateTime\n"; + EXPECTED_DUMP += "(0008,0030) TM [120000] # 6, 1 StudyTime\n"; + EXPECTED_DUMP += "(0008,0033) TM [092557] # 6, 1 ContentTime\n"; + EXPECTED_DUMP += "(0008,0050) SH (no value available) # 0, 0 AccessionNumber\n"; + EXPECTED_DUMP += "(0008,0060) CS [CT] # 2, 1 Modality\n"; + EXPECTED_DUMP += "(0008,0070) LO [Open Connections] # 16, 1 Manufacturer\n"; + EXPECTED_DUMP += "(0008,0090) PN (no value available) # 0, 0 ReferringPhysicianName\n"; + EXPECTED_DUMP += "(0008,103e) LO [Test Description] # 16, 1 SeriesDescription\n"; + EXPECTED_DUMP += "(0008,1090) LO [OC CT] # 6, 1 ManufacturerModelName\n"; + EXPECTED_DUMP += "(0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + EXPECTED_DUMP += "(0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + EXPECTED_DUMP + += "(0008,9207) CS [VOLUME_RENDER] # 14, 1 VolumeBasedCalculationTechnique\n"; + EXPECTED_DUMP += "(0010,0010) PN [Bond^James] # 10, 1 PatientName\n"; + EXPECTED_DUMP += "(0010,0020) LO [007] # 4, 1 PatientID\n"; + EXPECTED_DUMP += "(0010,0030) DA [19771007] # 8, 1 PatientBirthDate\n"; + EXPECTED_DUMP += "(0010,0040) CS (no value available) # 0, 0 PatientSex\n"; + EXPECTED_DUMP += "(0010,1010) AS [040Y] # 4, 1 PatientAge\n"; + EXPECTED_DUMP += "(0018,1000) LO [4711] # 4, 1 DeviceSerialNumber\n"; + EXPECTED_DUMP += "(0018,1020) LO [0.1] # 4, 1 SoftwareVersions\n"; + EXPECTED_DUMP += "(0018,5100) CS [HFS] # 4, 1 PatientPosition\n"; + EXPECTED_DUMP += "(0018,9004) CS [RESEARCH] # 8, 1 ContentQualification\n"; + EXPECTED_DUMP += "(0018,9073) FD 2 # 8, 1 AcquisitionDuration\n"; + EXPECTED_DUMP + += "(0020,000d) UI [1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811] # 56, 1 StudyInstanceUID\n"; + EXPECTED_DUMP + += "(0020,000e) UI [1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812] # 56, 1 SeriesInstanceUID\n"; + EXPECTED_DUMP += "(0020,0010) SH [1] # 2, 1 StudyID\n"; + EXPECTED_DUMP += "(0020,0011) IS [1] # 2, 1 SeriesNumber\n"; + EXPECTED_DUMP += "(0020,0013) IS [1] # 2, 1 InstanceNumber\n"; + EXPECTED_DUMP += "(0020,0052) UI [2.25.30853397773651184949181049330553108086] # 44, 1 FrameOfReferenceUID\n"; + EXPECTED_DUMP += "(0020,0242) UI [1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813] # 56, 1 " + "SOPInstanceUIDOfConcatenationSource\n"; + EXPECTED_DUMP += "(0020,1040) LO (no value available) # 0, 0 PositionReferenceIndicator\n"; + EXPECTED_DUMP + += "(0020,9161) UI [1.2.276.0.7230010.3.1.4.8323329.23689.1571391649.103636] # 56, 1 ConcatenationUID\n"; + EXPECTED_DUMP += "(0020,9162) US 1 # 2, 1 InConcatenationNumber\n"; + EXPECTED_DUMP += "(0020,9163) US $InConcatenationTotalNumber# 2, 1 InConcatenationTotalNumber\n"; + EXPECTED_DUMP += "(0020,9221) SQ (Sequence with explicit length #=1) # 0, 1 DimensionOrganizationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0020,9222) SQ (Sequence with explicit length #=2) # 0, 1 DimensionIndexSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9056) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9057) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += "(0020,9228) UL 0 # 4, 1 ConcatenationFrameOffsetNumber\n"; + EXPECTED_DUMP += "(0028,0002) US 1 # 2, 1 SamplesPerPixel\n"; + EXPECTED_DUMP += "(0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation\n"; + EXPECTED_DUMP += "(0028,0008) IS [1] # 2, 1 NumberOfFrames\n"; + EXPECTED_DUMP += "(0028,0010) US $Rows# 2, 1 Rows\n"; + EXPECTED_DUMP += "(0028,0011) US $Columns# 2, 1 Columns\n"; + EXPECTED_DUMP += "(0028,0100) US 16 # 2, 1 BitsAllocated\n"; + EXPECTED_DUMP += "(0028,0101) US 16 # 2, 1 BitsStored\n"; + EXPECTED_DUMP += "(0028,0102) US 15 # 2, 1 HighBit\n"; + EXPECTED_DUMP += "(0028,0103) US 0 # 2, 1 PixelRepresentation\n"; + EXPECTED_DUMP += "(0028,0301) CS [NO] # 2, 1 BurnedInAnnotation\n"; + EXPECTED_DUMP += "(0028,2110) CS [00] # 2, 1 LossyImageCompression\n"; + EXPECTED_DUMP += "(0040,0555) SQ (Sequence with explicit length #=0) # 0, 1 AcquisitionContextSequence\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(2050,0020) CS [IDENTITY] # 8, 1 PresentationLUTShape\n"; + EXPECTED_DUMP + += "(5200,9229) SQ (Sequence with explicit length #=1) # 0, 1 SharedFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=18) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9301) SQ (Sequence with explicit length #=1) # 0, 1 CTAcquisitionTypeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9302) CS [CONSTANT_ANGLE] # 14, 1 AcquisitionType\n"; + EXPECTED_DUMP += " (0018,9303) FD 0.1 # 8, 1 TubeAngle\n"; + EXPECTED_DUMP += " (0018,9333) CS [YES] # 4, 1 ConstantVolumeFlag\n"; + EXPECTED_DUMP += " (0018,9334) CS [NO] # 2, 1 FluoroscopyFlag\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9304) SQ (Sequence with explicit length #=1) # 0, 1 CTAcquisitionDetailsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,0090) DS [20] # 2, 1 DataCollectionDiameter\n"; + EXPECTED_DUMP += " (0018,1120) DS [5] # 2, 1 GantryDetectorTilt\n"; + EXPECTED_DUMP += " (0018,1130) DS [50] # 2, 1 TableHeight\n"; + EXPECTED_DUMP += " (0018,1140) CS [CW] # 2, 1 RotationDirection\n"; + EXPECTED_DUMP += " (0018,9305) FD 5 # 8, 1 RevolutionTime\n"; + EXPECTED_DUMP + += " (0018,9306) FD 1 # 8, 1 SingleCollimationWidth\n"; + EXPECTED_DUMP += " (0018,9307) FD 10 # 8, 1 TotalCollimationWidth\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9308) SQ (Sequence with explicit length #=1) # 0, 1 CTTableDynamicsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9309) FD 1 # 8, 1 TableSpeed\n"; + EXPECTED_DUMP += " (0018,9310) FD 0.1 # 8, 1 TableFeedPerRotation\n"; + EXPECTED_DUMP += " (0018,9311) FD 0.2 # 8, 1 SpiralPitchFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9312) SQ (Sequence with explicit length #=1) # 0, 1 CTGeometrySequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,1110) DS [0.5] # 4, 1 DistanceSourceToDetector\n"; + EXPECTED_DUMP += " (0018,9335) FD 5 # 8, 1 " + "DistanceSourceToDataCollectionCenter\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9314) SQ (Sequence with explicit length #=1) # 0, 1 CTReconstructionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,1100) DS [100] # 4, 1 ReconstructionDiameter\n"; + EXPECTED_DUMP += " (0018,1210) SH [DUMMY] # 6, 1 ConvolutionKernel\n"; + EXPECTED_DUMP + += " (0018,9315) CS [ALGO] # 4, 1 ReconstructionAlgorithm\n"; + EXPECTED_DUMP + += " (0018,9316) CS [DUMMYGROUP] # 10, 1 ConvolutionKernelGroup\n"; + EXPECTED_DUMP += " (0018,9319) FD 90 # 8, 1 ReconstructionAngle\n"; + EXPECTED_DUMP += " (0018,9320) SH [FILTER] # 6, 1 ImageFilter\n"; + EXPECTED_DUMP + += " (0018,9322) FD 0.1\\0.1 # 16, 2 ReconstructionPixelSpacing\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9321) SQ (Sequence with explicit length #=1) # 0, 1 CTExposureSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=10) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,115e) DS [0.5] # 4, 1 " + "ImageAndFluoroscopyAreaDoseProduct\n"; + EXPECTED_DUMP + += " (0018,1271) FD 0.6 # 8, 1 WaterEquivalentDiameter\n"; + EXPECTED_DUMP += " (0018,1272) SQ (Sequence with explicit length #=1) # 0, 1 " + "WaterEquivalentDiameterCalculationMethodCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [113987] # 6, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [AAPM 220] # 8, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9323) CS [WEIRD] # 6, 1 ExposureModulationType\n"; + EXPECTED_DUMP += " (0018,9324) FD 0.2 # 8, 1 EstimatedDoseSaving\n"; + EXPECTED_DUMP += " (0018,9328) FD 0.4 # 8, 1 ExposureTimeInms\n"; + EXPECTED_DUMP += " (0018,9330) FD 0.7 # 8, 1 XRayTubeCurrentInmA\n"; + EXPECTED_DUMP += " (0018,9332) FD 0.3 # 8, 1 ExposureInmAs\n"; + EXPECTED_DUMP += " (0018,9345) FD 0.1 # 8, 1 CTDIvol\n"; + EXPECTED_DUMP + += " (0018,9346) SQ (Sequence with explicit length #=1) # 0, 1 CTDIPhantomTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [113682] # 6, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [ACR Accreditation Phantom - CT] # 30, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9325) SQ (Sequence with explicit length #=1) # 0, 1 CTXRayDetailsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0060) DS [5] # 2, 1 KVP\n"; + EXPECTED_DUMP += " (0018,1160) SH [FILTER_TYPE] # 12, 1 FilterType\n"; + EXPECTED_DUMP += " (0018,1190) DS [4.4\\4.4\\4.4\\4.4] # 16, 4 FocalSpots\n"; + EXPECTED_DUMP += " (0018,7050) CS [FILTER_MATERIAL] # 16, 1 FilterMaterial\n"; + EXPECTED_DUMP + += " (0018,9351) FL 2 # 4, 1 CalciumScoringMassFactorPatient\n"; + EXPECTED_DUMP += " (0018,9352) FL 1\\1\\1 # 12, 3 " + "CalciumScoringMassFactorDevice\n"; + EXPECTED_DUMP += " (0018,9353) FL 3 # 4, 1 EnergyWeightingFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9326) SQ (Sequence with explicit length #=1) # 0, 1 CTPositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9313) FD 2\\2\\2 # 24, 3 DataCollectionCenterPatient\n"; + EXPECTED_DUMP += " (0018,9318) FD 1\\1\\1 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + EXPECTED_DUMP += " (0018,9327) FD 100 # 8, 1 TablePosition\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9329) SQ (Sequence with explicit length #=1) # 0, 1 CTImageFrameTypeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,9007) CS [ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM] # 32, 4 FrameType\n"; + EXPECTED_DUMP += " (0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + EXPECTED_DUMP += " (0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + EXPECTED_DUMP + += " (0008,9207) CS [VOLUME_RENDER] # 14, 1 VolumeBasedCalculationTechnique\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9360) SQ (Sequence with explicit length #=1) # 0, 1 CTAdditionalXRaySourceSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=8) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0060) DS [5] # 2, 1 KVP\n"; + EXPECTED_DUMP + += " (0018,0090) DS [1] # 2, 1 DataCollectionDiameter\n"; + EXPECTED_DUMP += " (0018,1160) SH [FILTER_TYPE] # 12, 1 FilterType\n"; + EXPECTED_DUMP += " (0018,1190) DS [4.4\\4.4\\4.4\\4.4] # 16, 4 FocalSpots\n"; + EXPECTED_DUMP += " (0018,7050) CS [FILTER_MATERIAL] # 16, 1 FilterMaterial\n"; + EXPECTED_DUMP += " (0018,9330) FD 6 # 8, 1 XRayTubeCurrentInmA\n"; + EXPECTED_DUMP += " (0018,9332) FD 3 # 8, 1 ExposureInmAs\n"; + EXPECTED_DUMP += " (0018,9353) FL 2 # 4, 1 EnergyWeightingFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9477) SQ (Sequence with explicit length #=1) # 0, 1 " + "IrradiationEventIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0008,3010) UI [2.25.30853892236613436472911970638347155062] # 44, 1 IrradiationEventUID\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9071) SQ (Sequence with explicit length #=1) # 0, 1 FrameAnatomySequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0008,2218) SQ (Sequence with explicit length #=1) # 0, 1 AnatomicRegionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [12738006] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Brain] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9072) CS [B] # 2, 1 FrameLaterality\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9113) SQ (Sequence with explicit length #=1) # 0, 1 PlanePositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0032) DS [0.0\\0.0\\0.0] # 12, 3 ImagePositionPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9116) SQ (Sequence with explicit length #=1) # 0, 1 PlaneOrientationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0037) DS [1.0\\0.0\\0.0\\0.0\\1.0\\0.0] # 24, 6 ImageOrientationPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9310) SQ (Sequence with explicit length #=1) # 0, 1 TemporalPositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,930d) FD 1 # 8, 1 TemporalPositionTimeOffset\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0028,9110) SQ (Sequence with explicit length #=1) # 0, 1 PixelMeasuresSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0050) DS [1.0] # 4, 1 SliceThickness\n"; + EXPECTED_DUMP += " (0018,0088) DS [0.05] # 4, 1 SpacingBetweenSlices\n"; + EXPECTED_DUMP += " (0028,0030) DS [0.1\\0.1] # 8, 2 PixelSpacing\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0028,9132) SQ (Sequence with explicit length #=1) # 0, 1 FrameVOILUTSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0028,1050) DS [1000] # 4, 1 WindowCenter\n"; + EXPECTED_DUMP += " (0028,1051) DS [2000] # 4, 1 WindowWidth\n"; + EXPECTED_DUMP + += " (0028,1055) LO [BRAIN] # 6, 1 WindowCenterWidthExplanation\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0028,9145) SQ (Sequence with explicit length #=1) # 0, 1 PixelValueTransformationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0028,1052) DS [0] # 2, 1 RescaleIntercept\n"; + EXPECTED_DUMP += " (0028,1053) DS [1] # 2, 1 RescaleSlope\n"; + EXPECTED_DUMP += " (0028,1054) LO [HU] # 2, 1 RescaleType\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += "(5200,9230) SQ (Sequence with explicit length #=1) # 0, 1 PerFrameFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 1 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 1 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\1 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(7fe0,0010) OW 0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001\\0001... # " + "32000000, 1 PixelData\n"; + OFStringStream ss; + ss << NUM_ROWS; + OFString numRows(ss.str().c_str()); + size_t spaces = 41 - numRows.length(); + numRows.append(spaces, ' '); + ss.str(""); + ss << NUM_COLS; + OFString numCols(ss.str().c_str()); + spaces = 41 - numCols.length(); + numCols.append(spaces, ' '); + ss.str(""); + ss << NUM_FRAMES; + OFString numFrames(ss.str().c_str()); + spaces = 41 - numFrames.length(); + numFrames.append(spaces, ' '); + OFStringUtil::replace_all(EXPECTED_DUMP, "$Rows", numRows); + OFStringUtil::replace_all(EXPECTED_DUMP, "$Columns", numCols); + OFStringUtil::replace_all(EXPECTED_DUMP, "$InConcatenationTotalNumber", numFrames); +} + +static void checkCreatedObject(const OFString& ds_dump) +{ + OFBool dump_ok = (ds_dump == EXPECTED_DUMP); + OFCHECK(dump_ok); + if (!dump_ok) + { + CERR << "Dump produced: " << OFendl << ds_dump << OFendl; + CERR << "------------------------------------" << OFendl; + CERR << "Dump expected: " << OFendl << EXPECTED_DUMP << OFendl; + CERR << "------------------------------------" << OFendl; + } +} diff --git a/dcmect/tests/t_roundtrip.cc b/dcmect/tests/t_roundtrip.cc new file mode 100644 index 00000000..3cdeb907 --- /dev/null +++ b/dcmect/tests/t_roundtrip.cc @@ -0,0 +1,990 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Tests for creating and loading Enhanced CT objects + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofstrutl.h" +#include "dcmtk/ofstd/oftempf.h" +#include "dcmtk/ofstd/oftest.h" + +#include "dcmtk/dcmect/enhanced_ct.h" + +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmfg/fgctacquisitiondetails.h" +#include "dcmtk/dcmfg/fgctacquisitiontype.h" +#include "dcmtk/dcmfg/fgctadditionalxraysource.h" +#include "dcmtk/dcmfg/fgctexposure.h" +#include "dcmtk/dcmfg/fgctgeometry.h" +#include "dcmtk/dcmfg/fgctimageframetype.h" +#include "dcmtk/dcmfg/fgctposition.h" +#include "dcmtk/dcmfg/fgctreconstruction.h" +#include "dcmtk/dcmfg/fgcttabledynamics.h" +#include "dcmtk/dcmfg/fgctxraydetails.h" +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgframeanatomy.h" +#include "dcmtk/dcmfg/fgframevoilut.h" +#include "dcmtk/dcmfg/fgirradiationeventid.h" +#include "dcmtk/dcmfg/fgpixeltransform.h" +#include "dcmtk/dcmfg/fgpixmsr.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" +#include "dcmtk/dcmfg/fgtemporalposition.h" + +static OFLogger tRoundLogger = OFLog::getLogger("dcmtk.test.t_roundtrip"); + +// Do not change values below since +// a) The expected dataset (dump) is made for these values +// b) Total pixel data length in this test must not be bigger than +// 4 GB, otherwise the calls to writeDataset() will fail. +// The test dcmect/tests/t_huge_concat.cc allows for exercising +// "unlimited" pixel data size using writeConcatenation() on all +// occassions. + +static const Uint16 NUM_ROWS = 2; +static const Uint16 NUM_COLS = 2; +static const Uint16 NUM_FRAMES = 2; +static const size_t NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS; +static const size_t NUM_FRAMES_CONCAT = 1; + +static OFString EXPECTED_DUMP; + +static void prepareExpectedDump(); +static EctEnhancedCT* create(); +static void configureIOD(EctEnhancedCT* ct); +static void setGenericValues(EctEnhancedCT* ct); +static void addSharedFGs(EctEnhancedCT* ct); +static void addFrames(EctEnhancedCT* ct); +static void addDimensions(EctEnhancedCT* ct); +static OFString write(EctEnhancedCT* ct, DcmDataset& ds); +static void checkCreatedObject(const OFString& ds_dump); +static void writeAndCheckConcatenation(EctEnhancedCT* ct, OFList& concats); +static void checkConcatenationInstance(size_t numInstance, EctEnhancedCT* srcInstance, DcmDataset* concatInstance); +static void loadAndCheckConcatenation(const OFList& concats); + +OFTEST(dcmect_roundtrip) +{ + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK(dcmDataDict.isDictionaryLoaded()); + return; + } + + // Creation + EctEnhancedCT* ct = create(); + configureIOD(ct); + setGenericValues(ct); + addSharedFGs(ct); + addFrames(ct); + addDimensions(ct); + + // Write to dataset and compare its dump with expected result + DcmFileFormat dcmff; + DcmDataset* ds = dcmff.getDataset(); + prepareExpectedDump(); + OFString dset_dump = write(ct, *ds); + checkCreatedObject(dset_dump); + + // Save to disk, and re-load to test import + OFTempFile tf; + OFString temp_fn = tf.getFilename(); + OFCHECK(!temp_fn.empty()); + OFCHECK(ct->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good()); + + // Read object from dataset into EctEnhancedCT object, write again to dataset and + // check whether daset before saving to file is identical to object after loading from + // disk and writing to dataset + delete ct; + ct = NULL; + ds->clear(); + OFCHECK(EctEnhancedCT::loadFile(temp_fn, ct).good()); + OFCHECK(ct != NULL); + if (ct) + { + dset_dump = write(ct, *ds); + checkCreatedObject(dset_dump); + } + OFList concats; + if (ct) + { + writeAndCheckConcatenation(ct, concats); + delete ct; + } + OFCHECK(!concats.empty()); + if (!concats.empty()) + { + loadAndCheckConcatenation(concats); + } + OFListIterator(OFFilename) it = concats.begin(); + while (it != concats.end()) + { + OFStandard::deleteFile(*it); + it++; + } +} + +static EctEnhancedCT* create() +{ + IODEnhGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1"); + EctEnhancedCT* ct = NULL; + OFCondition result; + result = EctEnhancedCT::create(ct, + NUM_ROWS, + NUM_COLS, + OFFalse, + EctTypes::E_ImageType1_Original, + EctTypes::DT_ImageType3_Volume, + EctTypes::DT_ImageType4_Maximum, + "1" /* instance number */, + EctTypes::E_ContQuali_Research, + EctTypes::E_PixelPres_Monochrome, + EctTypes::E_VolProps_Volume, + EctTypes::DT_VolBasedCalcTechnique_VolumeRender, + eq, + "20190801120000" /* acquisition date */, + 2.0 /* acquisition duration */); + + OFCHECK(result.good()); + OFCHECK(ct != OFnullptr); + return ct; +} + +static void configureIOD(EctEnhancedCT* ct) +{ + if (!ct) + return; +} + +static void setGenericValues(EctEnhancedCT* ct) +{ + if (!ct) + return; + OFCHECK(ct->getPatient().setPatientName("Bond^James").good()); + OFCHECK(ct->getPatient().setPatientID("007").good()); + OFCHECK(ct->getPatient().setPatientBirthDate("19771007").good()); + OFCHECK(ct->getStudy().setStudyDate("20190801").good()); + OFCHECK(ct->getStudy().setStudyTime("120000").good()); + OFCHECK(ct->getStudy().setStudyID("1").good()); + OFCHECK(ct->getPatientStudy().setPatientAge("040Y").good()); + OFCHECK(ct->getSeries().setSeriesDescription("Test Description").good()); + OFCHECK(ct->getSeries().setSeriesNumber("1").good()); + OFCHECK(ct->getSeries().setPatientPosition("HFS").good()); + + // Those values are usually computed automatically. UIDS are generated and date/times are set to current values. + // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually, + // so that they are not overwritten with new, automatically created values later. + OFCHECK(ct->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good()); + OFCHECK(ct->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good()); + OFCHECK(ct->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good()); + OFCHECK(ct->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good()); + + OFCHECK(ct->getIODMultiFrameFGModule().setContentTime("092557").good()); + OFCHECK(ct->getIODMultiFrameFGModule().setContentDate("20190816").good()); +} + +static void addSharedFGs(EctEnhancedCT* ct) +{ + if (!ct) + return; + + FGPixelMeasures meas; + OFCHECK(meas.setPixelSpacing("0.1\\0.1").good()); + OFCHECK(meas.setSliceThickness("1.0").good()); + OFCHECK(meas.setSpacingBetweenSlices("0.05").good()); + + FGPlanePosPatient planpo; + OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good()); + + FGPlaneOrientationPatient planor; + OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good()); + + FGFrameAnatomy ana; + OFCHECK(ana.setLaterality(FGFrameAnatomy::LATERALITY_BOTH).good()); + OFCHECK(ana.getAnatomy().getAnatomicRegion().set("12738006", "SCT", "Brain").good()); + + FGFrameVOILUT voi; + OFCHECK(voi.setCenterWidthExplanation(1000, 2000, FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_Brain).good()); + + FGIrradiationEventIdentification irr; + OFCHECK(irr.setIrradiationEventUID("2.25.30853892236613436472911970638347155062").good()); + + FGCTImageFrameType itype; + OFCHECK(itype.setFrameType("ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM").good()); + OFCHECK(itype.setPixelPresentation(FGCTImageFrameType::E_PixelPres_Monochrome).good()); + OFCHECK(itype.setVolumetricProperties(FGCTImageFrameType::E_VolProp_Volume).good()); + OFCHECK(itype.setVolumeBasedCalculationTechnique(FGCTImageFrameType::DT_VolBasedCalcTechnique_VolumeRender).good()); + + FGCTAcquisitionType atype; + OFCHECK(atype.setAcquisitionType(FGCTAcquisitionType::DT_AcquisitionType_ConstantAngle).good()); + OFCHECK(atype.setTubeAngle(0.1).good()); + OFCHECK(atype.setConstantVolumeFlag(FGCTAcquisitionType::E_ConstVol_Yes).good()); + OFCHECK(atype.setFluoroscopyFlag(FGCTAcquisitionType::E_Fluoroscopy_No).good()); + + FGCTAcquisitionDetails adetails; + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* item = new FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem(); + OFCHECK(item->setRotationDirection(FGCTAcquisitionDetails::E_RotationDirection_CW).good()); + OFCHECK(item->setRevolutionTime(5).good()); + OFCHECK(item->setSingleCollimationWidth(1).good()); + OFCHECK(item->setTotalCollimationWidth(10).good()); + OFCHECK(item->setTableHeight(50).good()); + OFCHECK(item->setGantryDetectorTilt(5).good()); + OFCHECK(item->setDataCollectionDiameter(20).good()); + adetails.getCTAcquisitionDetailsItems().push_back(item); + + FGCTTableDynamics dyn; + FGCTTableDynamics::FGCTTableDynamicsItem* dyn_item = new FGCTTableDynamics::FGCTTableDynamicsItem; + OFCHECK(dyn_item); + if (dyn_item) + { + OFCHECK(dyn_item->setTableSpeed(1.0).good()); + OFCHECK(dyn_item->setTableFeedPerRotation(0.1).good()); + OFCHECK(dyn_item->setSpiralPitchFactor(0.2).good()); + dyn.getCTTableDynamicsItems().push_back(dyn_item); + } + + FGCTPosition pos; + OFCHECK(pos.setTablePosition(100.0).good()); + OFCHECK(pos.setReconstructionTargetCenterPatient(OFVector(3, 1.0)).good()); + OFCHECK(pos.setDataCollectionCenterPatient(OFVector(3, 2.0)).good()); + + FGCTGeometry geo; + FGCTGeometry::FGCTGeometryItem* geo_item = new FGCTGeometry::FGCTGeometryItem; + if (geo_item) + { + OFCHECK(geo_item->setDistanceSourceToDataCollectionCenter(5.0).good()); + OFCHECK(geo_item->setDistanceSourceToDetector(0.5).good()); + geo.getCTGeometryItems().push_back(geo_item); + } + + FGCTReconstruction rec; + OFCHECK(rec.setConvolutionKernel("DUMMY").good()); + OFCHECK(rec.setConvolutionKernelGroup("DUMMYGROUP").good()); + OFCHECK(rec.setImageFilter("FILTER").good()); + OFCHECK(rec.setReconstructionAlgorithm("ALGO").good()); + OFCHECK(rec.setReconstructionAngle(90.0).good()); + OFCHECK(rec.setReconstructionDiameter(100.0).good()); + // Not permitted if Reconstruction Diameter is provided instead + // OFCHECK(rec.setReconstructionFieldOfView(100.0, 100.0).good()); + OFCHECK(rec.setReconstructionPixelSpacing(0.1, 0.1).good()); + + FGCTExposure exp; + FGCTExposure::FGCTExposureItem* exp_item = new FGCTExposure::FGCTExposureItem; + if (exp_item) + { + OFCHECK(exp_item->setCTDIVol(0.1).good()); + CodeSequenceMacro* phantom_item = new CodeSequenceMacro("113682", "DCM", "ACR Accreditation Phantom - CT"); + exp_item->getCTDIPhantomTypeCodeSequence().push_back(phantom_item); + OFCHECK(exp_item->setEstimatedDoseSaving(0.2).good()); + OFCHECK(exp_item->setExposureInMas(0.3).good()); + OFCHECK(exp_item->setExposureModulationType("WEIRD").good()); + OFCHECK(exp_item->setExposureTimeInMs(0.4).good()); + OFCHECK(exp_item->setImageAndFluoroscopyAreaDoseProduct(0.5).good()); + OFCHECK(exp_item->setWaterEquivalentDiameter(0.6).good()); + CodeSequenceMacro* water_code = new CodeSequenceMacro("113987", "DCM", "AAPM 220"); + exp_item->getWaterEquivalentDiameterCalculationMethodCodeSequence().push_back(water_code); + OFCHECK(exp_item->setXRayTubeCurrentInMa(0.7).good()); + exp.getCTExposureItems().push_back(exp_item); + } + + FGCTXRayDetails det; + FGCTXRayDetails::FGCTXRayDetailsItem* det_item = new FGCTXRayDetails::FGCTXRayDetailsItem; + if (det_item) + { + OFCHECK(det_item->setCalciumScoringMassFactorDevice(OFVector(3, 1)).good()); + OFCHECK(det_item->setCalciumScoringMassFactorPatient(2).good()); + OFCHECK(det_item->setEnergyWeightingFactor(3).good()); + OFCHECK(det_item->setFilterMaterial("FILTER_MATERIAL").good()); + OFCHECK(det_item->setFilterType("FILTER_TYPE").good()); + OFCHECK(det_item->setFocalSpots(OFVector(4, 4.4)).good()); + OFCHECK(det_item->setKVP(5.0).good()); + det.getCTXRayDetailsItems().push_back(det_item); + } + + FGPixelValueTransformation trans; + trans.setFGType(FGPixelValueTransformation::E_PixelValTrans_CT); + trans.setRescaleIntercept("0"); + trans.setRescaleSlope("1"); + trans.setRescaleType("HU"); + + FGCTAdditionalXRaySource asrc; + FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem* asrc_item + = new FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem; + if (asrc_item) + { + OFCHECK(asrc_item->setDataCollectionDiameter(1.0).good()); + OFCHECK(asrc_item->setEnergyWeightingFactor(2.0).good()); + OFCHECK(asrc_item->setExposureInmAs(3.0).good()); + OFCHECK(asrc_item->setFilterMaterial("FILTER_MATERIAL").good()); + OFCHECK(asrc_item->setFilterType("FILTER_TYPE").good()); + OFCHECK(asrc_item->setFocalSpots(OFVector(4, 4.4)).good()); + OFCHECK(asrc_item->setKVP(5).good()); + OFCHECK(asrc_item->setXRayTubeCurrentInmA(6).good()); + asrc.getCTAdditionalXRaySourceItems().push_back(asrc_item); + } + + FGTemporalPosition tempos; + OFCHECK(tempos.setTemporalPositionTimeOffset(1.0).good()); + + OFCHECK(ct->addForAllFrames(meas).good()); + OFCHECK(ct->addForAllFrames(planpo).good()); + OFCHECK(ct->addForAllFrames(planor).good()); + OFCHECK(ct->addForAllFrames(ana).good()); + OFCHECK(ct->addForAllFrames(voi).good()); + OFCHECK(ct->addForAllFrames(irr).good()); + OFCHECK(ct->addForAllFrames(itype).good()); + OFCHECK(ct->addForAllFrames(atype).good()); + OFCHECK(ct->addForAllFrames(adetails).good()); + OFCHECK(ct->addForAllFrames(dyn).good()); + OFCHECK(ct->addForAllFrames(pos).good()); + OFCHECK(ct->addForAllFrames(geo).good()); + OFCHECK(ct->addForAllFrames(rec).good()); + OFCHECK(ct->addForAllFrames(exp).good()); + OFCHECK(ct->addForAllFrames(det).good()); + OFCHECK(ct->addForAllFrames(trans).good()); + OFCHECK(ct->addForAllFrames(asrc).good()); + OFCHECK(ct->addForAllFrames(tempos).good()); +} + +static void addFrames(EctEnhancedCT* ct) +{ + if (!ct) + return; + + FGFrameContent* fg = new FGFrameContent(); + fg->setStackID("1"); + OFCHECK(fg); + if (fg) + { + EctEnhancedCT::FramesType frames = ct->getFrames(); + for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++) + { + OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good()); + OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDuration(0.001).good()); + OFCHECK(fg->setInStackPositionNumber(frameNo).good()); + OFCHECK(fg->setDimensionIndexValues(1, 0).good()); + OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good()); + OFVector groups; + groups.push_back(fg); + + Uint16* data = new Uint16[NUM_PIXELS_PER_FRAME]; + for (size_t i = 0; i < NUM_PIXELS_PER_FRAME; ++i) + { + data[i] = frameNo; + } + OFCHECK( + OFget >(&frames)->addFrame(data, NUM_PIXELS_PER_FRAME, groups).good()); + delete[] data; + } + } + delete fg; +} + +static void addDimensions(EctEnhancedCT* ct) +{ + if (!ct) + return; + IODMultiframeDimensionModule& dims = ct->getDimensions(); + OFCHECK(dims.addDimensionIndex( + DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM") + .good()); + OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber, + "2.25.30855560781715986879861690673941231222", + DCM_FrameContentSequence, + "STACK_DIM") + .good()); + OFunique_ptr org( + new IODMultiframeDimensionModule::DimensionOrganizationItem); + if (org) + { + org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222"); + dims.getDimensionOrganizationSequence().push_back(org.release()); + } +} + +static OFString write(EctEnhancedCT* ct, DcmDataset& ds) +{ + OFCondition result = ct->writeDataset(ds); + OFCHECK(result.good()); + if (result.bad()) + { + OFLOG_ERROR(tRoundLogger, "Writing Enhanced CT dataset failed: " << result.text() << OFendl); + } + // Make dump and return it + OFStringStream sstream; + ds.print(sstream); + OFSTRINGSTREAM_GETOFSTRING(sstream, dump); + return dump; +} + +static void writeAndCheckConcatenation(EctEnhancedCT* ct, OFList& concats) +{ + ConcatenationCreator cc; + cc.setCfgFramesPerInstance(NUM_FRAMES_CONCAT); + OFCHECK(ct->writeConcatenation(cc).good()); + size_t numInstances = cc.getNumInstances(); + OFCHECK(numInstances == NUM_FRAMES); + OFCondition result; + for (size_t n = 0; n < numInstances; n++) + { + OFStringStream s; + s << "concat_" << n << "_"; + OFTempFile tf(O_RDWR, "", s.str().c_str(), ".dcm"); + result = cc.writeNextInstance(tf.getFilename()); + OFCHECK(result.good()); + if (result.good()) + { + DcmFileFormat concat; + OFCHECK(concat.loadFile(tf.getFilename()).good()); + checkConcatenationInstance(n, ct, concat.getDataset()); + concats.push_back(tf.getFilename()); + tf.stealFile(); + } + } +} + +static void checkConcatenationInstance(size_t numInstance, EctEnhancedCT* srcInstance, DcmDataset* concatInstance) +{ + EctEnhancedCT* concat = NULL; + OFCHECK(EctEnhancedCT::loadDataset(*concatInstance, concat).good()); + if (concat) + { + size_t numFrames; + numFrames = concat->getNumberOfFrames(); + OFCHECK(numFrames == 1); + IODMultiFrameFGModule::ConcatenationInfo& ci = concat->getConcatenationInfo(); + OFString val; + OFCHECK(ci.getConcatenationUID(val).good()); + OFCHECK(DcmUniqueIdentifier::checkStringValue(val, "1").good()); + Uint32 frameOffsetNo = 0; + OFCHECK(ci.getConcatenationFrameOffsetNumber(frameOffsetNo).good()); + OFCHECK(frameOffsetNo == numInstance); + Uint16 inConcatNo = 0; + OFCHECK(ci.getInConcatenationNumber(inConcatNo).good()); + OFCHECK(inConcatNo == numInstance + 1); + Uint16 concatTotalNo = 0; + OFCHECK(ci.getInConcatenationTotalNumber(concatTotalNo).good()); + OFCHECK(concatTotalNo == NUM_FRAMES); + + OFString srcUID; + OFCHECK(ci.getSOPInstanceUIDOfConcatenationSource(srcUID).good()); + OFCHECK(srcInstance->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID == val); + + OFCHECK(concat->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID != val); + + FunctionalGroups::const_iterator srcShared = srcInstance->getFunctionalGroups().getShared()->begin(); + FunctionalGroups::const_iterator cShared = concat->getFunctionalGroups().getShared()->begin(); + size_t numShared = 0; + do + { + OFCHECK(srcShared->second->compare(*cShared->second) == 0); + srcShared++; + cShared++; + numShared++; + } while ((srcShared != srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared != concat->getFunctionalGroups().getShared()->end())); + OFCHECK((srcShared == srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared == concat->getFunctionalGroups().getShared()->end())); + DcmSequenceOfItems* cPerFrame = NULL; + OFCHECK(concatInstance->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, cPerFrame).good()); + + if (cPerFrame) + { + OFCHECK(cPerFrame->card() == 1); + } + + OFBool perFrame = OFFalse; + FGBase* fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTACQUISITIONDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTACQUISITIONTYPE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTADDITIONALXRAYSOURCE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTEXPOSURE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTGEOMETRY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTIMAGEFRAMETYPE, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTPOSITION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTRECONSTRUCTION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTTABLEDYNAMICS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTXRAYDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_CTXRAYDETAILS, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMECONTENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFTrue); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEVOILUTMETA, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMEANATOMY, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_IRRADIATIONEVENTIDENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PIXELVALUETRANSMETA, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_IRRADIATIONEVENTIDENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PIXELMEASURES, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEPOSPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEORIENTPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_TEMPORALPOSITION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + EctEnhancedCT::FramesType frames = concat->getFrames(); + Uint16* frame = OFget >(&frames)->getFrame(0); + OFCHECK(frame != OFnullptr); + // Check that all pixels are set to their original source instances frame number (starting from 1) + for (size_t pix = 0; pix < NUM_PIXELS_PER_FRAME; pix++) + { + OFCHECK(frame[pix] == numInstance + 1); + } + delete concat; + } +} + +void loadAndCheckConcatenation(const OFList& concats) +{ + ConcatenationLoader cl; + OFCondition result = cl.scan(concats); + OFCHECK(result.good()); + if (result.good()) + { + DcmDataset merged; + EctEnhancedCT* mergedCT = NULL; + result = EctEnhancedCT::loadConcatenation(cl, cl.getInfo().begin()->first, mergedCT); + if (result.good()) + { + OFStringStream s; + DcmDataset d; + result = mergedCT->writeDataset(d); + OFCHECK(result.good()); + if (result.good()) + { + // patch in old timestamp to match dump + OFCHECK(d.putAndInsertOFStringArray(DCM_ContentDate, "20190816").good()); + OFCHECK(d.putAndInsertOFStringArray(DCM_ContentTime, "092557").good()); + d.print(s); + checkCreatedObject(s.str().c_str()); + delete mergedCT; + } + } + } +} + +static void prepareExpectedDump() +{ + EXPECTED_DUMP += "\n"; + EXPECTED_DUMP += "# Dicom-Data-Set\n"; + EXPECTED_DUMP += "# Used TransferSyntax: Little Endian Explicit\n"; + EXPECTED_DUMP += "(0008,0008) CS [ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM] # 32, 4 ImageType\n"; + EXPECTED_DUMP += "(0008,0016) UI =EnhancedCTImageStorage # 28, 1 SOPClassUID\n"; + EXPECTED_DUMP + += "(0008,0018) UI [1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813] # 56, 1 SOPInstanceUID\n"; + EXPECTED_DUMP += "(0008,0020) DA [20190801] # 8, 1 StudyDate\n"; + EXPECTED_DUMP += "(0008,0023) DA [20190816] # 8, 1 ContentDate\n"; + EXPECTED_DUMP += "(0008,002a) DT [20190801120000] # 14, 1 AcquisitionDateTime\n"; + EXPECTED_DUMP += "(0008,0030) TM [120000] # 6, 1 StudyTime\n"; + EXPECTED_DUMP += "(0008,0033) TM [092557] # 6, 1 ContentTime\n"; + EXPECTED_DUMP += "(0008,0050) SH (no value available) # 0, 0 AccessionNumber\n"; + EXPECTED_DUMP += "(0008,0060) CS [CT] # 2, 1 Modality\n"; + EXPECTED_DUMP += "(0008,0070) LO [Open Connections] # 16, 1 Manufacturer\n"; + EXPECTED_DUMP += "(0008,0090) PN (no value available) # 0, 0 ReferringPhysicianName\n"; + EXPECTED_DUMP += "(0008,103e) LO [Test Description] # 16, 1 SeriesDescription\n"; + EXPECTED_DUMP += "(0008,1090) LO [OC CT] # 6, 1 ManufacturerModelName\n"; + EXPECTED_DUMP += "(0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + EXPECTED_DUMP += "(0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + EXPECTED_DUMP + += "(0008,9207) CS [VOLUME_RENDER] # 14, 1 VolumeBasedCalculationTechnique\n"; + EXPECTED_DUMP += "(0010,0010) PN [Bond^James] # 10, 1 PatientName\n"; + EXPECTED_DUMP += "(0010,0020) LO [007] # 4, 1 PatientID\n"; + EXPECTED_DUMP += "(0010,0030) DA [19771007] # 8, 1 PatientBirthDate\n"; + EXPECTED_DUMP += "(0010,0040) CS (no value available) # 0, 0 PatientSex\n"; + EXPECTED_DUMP += "(0010,1010) AS [040Y] # 4, 1 PatientAge\n"; + EXPECTED_DUMP += "(0018,1000) LO [4711] # 4, 1 DeviceSerialNumber\n"; + EXPECTED_DUMP += "(0018,1020) LO [0.1] # 4, 1 SoftwareVersions\n"; + EXPECTED_DUMP += "(0018,5100) CS [HFS] # 4, 1 PatientPosition\n"; + EXPECTED_DUMP += "(0018,9004) CS [RESEARCH] # 8, 1 ContentQualification\n"; + EXPECTED_DUMP += "(0018,9073) FD 2 # 8, 1 AcquisitionDuration\n"; + EXPECTED_DUMP + += "(0020,000d) UI [1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811] # 56, 1 StudyInstanceUID\n"; + EXPECTED_DUMP + += "(0020,000e) UI [1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812] # 56, 1 SeriesInstanceUID\n"; + EXPECTED_DUMP += "(0020,0010) SH [1] # 2, 1 StudyID\n"; + EXPECTED_DUMP += "(0020,0011) IS [1] # 2, 1 SeriesNumber\n"; + EXPECTED_DUMP += "(0020,0013) IS [1] # 2, 1 InstanceNumber\n"; + EXPECTED_DUMP += "(0020,0052) UI [2.25.30853397773651184949181049330553108086] # 44, 1 FrameOfReferenceUID\n"; + EXPECTED_DUMP += "(0020,1040) LO (no value available) # 0, 0 PositionReferenceIndicator\n"; + EXPECTED_DUMP += "(0020,9221) SQ (Sequence with explicit length #=1) # 0, 1 DimensionOrganizationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0020,9222) SQ (Sequence with explicit length #=2) # 0, 1 DimensionIndexSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9056) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9057) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0028,0002) US 1 # 2, 1 SamplesPerPixel\n"; + EXPECTED_DUMP += "(0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation\n"; + EXPECTED_DUMP += "(0028,0008) IS [2] # 2, 1 NumberOfFrames\n"; + EXPECTED_DUMP += "(0028,0010) US 2 # 2, 1 Rows\n"; + EXPECTED_DUMP += "(0028,0011) US 2 # 2, 1 Columns\n"; + EXPECTED_DUMP += "(0028,0100) US 16 # 2, 1 BitsAllocated\n"; + EXPECTED_DUMP += "(0028,0101) US 16 # 2, 1 BitsStored\n"; + EXPECTED_DUMP += "(0028,0102) US 15 # 2, 1 HighBit\n"; + EXPECTED_DUMP += "(0028,0103) US 0 # 2, 1 PixelRepresentation\n"; + EXPECTED_DUMP += "(0028,0301) CS [NO] # 2, 1 BurnedInAnnotation\n"; + EXPECTED_DUMP += "(0028,2110) CS [00] # 2, 1 LossyImageCompression\n"; + EXPECTED_DUMP += "(0040,0555) SQ (Sequence with explicit length #=0) # 0, 1 AcquisitionContextSequence\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(2050,0020) CS [IDENTITY] # 8, 1 PresentationLUTShape\n"; + EXPECTED_DUMP + += "(5200,9229) SQ (Sequence with explicit length #=1) # 0, 1 SharedFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=18) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9301) SQ (Sequence with explicit length #=1) # 0, 1 CTAcquisitionTypeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9302) CS [CONSTANT_ANGLE] # 14, 1 AcquisitionType\n"; + EXPECTED_DUMP += " (0018,9303) FD 0.1 # 8, 1 TubeAngle\n"; + EXPECTED_DUMP += " (0018,9333) CS [YES] # 4, 1 ConstantVolumeFlag\n"; + EXPECTED_DUMP += " (0018,9334) CS [NO] # 2, 1 FluoroscopyFlag\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9304) SQ (Sequence with explicit length #=1) # 0, 1 CTAcquisitionDetailsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,0090) DS [20] # 2, 1 DataCollectionDiameter\n"; + EXPECTED_DUMP += " (0018,1120) DS [5] # 2, 1 GantryDetectorTilt\n"; + EXPECTED_DUMP += " (0018,1130) DS [50] # 2, 1 TableHeight\n"; + EXPECTED_DUMP += " (0018,1140) CS [CW] # 2, 1 RotationDirection\n"; + EXPECTED_DUMP += " (0018,9305) FD 5 # 8, 1 RevolutionTime\n"; + EXPECTED_DUMP + += " (0018,9306) FD 1 # 8, 1 SingleCollimationWidth\n"; + EXPECTED_DUMP += " (0018,9307) FD 10 # 8, 1 TotalCollimationWidth\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9308) SQ (Sequence with explicit length #=1) # 0, 1 CTTableDynamicsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,9309) FD 1 # 8, 1 TableSpeed\n"; + EXPECTED_DUMP += " (0018,9310) FD 0.1 # 8, 1 TableFeedPerRotation\n"; + EXPECTED_DUMP += " (0018,9311) FD 0.2 # 8, 1 SpiralPitchFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9312) SQ (Sequence with explicit length #=1) # 0, 1 CTGeometrySequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,1110) DS [0.5] # 4, 1 DistanceSourceToDetector\n"; + EXPECTED_DUMP += " (0018,9335) FD 5 # 8, 1 " + "DistanceSourceToDataCollectionCenter\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9314) SQ (Sequence with explicit length #=1) # 0, 1 CTReconstructionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,1100) DS [100] # 4, 1 ReconstructionDiameter\n"; + EXPECTED_DUMP += " (0018,1210) SH [DUMMY] # 6, 1 ConvolutionKernel\n"; + EXPECTED_DUMP + += " (0018,9315) CS [ALGO] # 4, 1 ReconstructionAlgorithm\n"; + EXPECTED_DUMP + += " (0018,9316) CS [DUMMYGROUP] # 10, 1 ConvolutionKernelGroup\n"; + EXPECTED_DUMP += " (0018,9319) FD 90 # 8, 1 ReconstructionAngle\n"; + EXPECTED_DUMP += " (0018,9320) SH [FILTER] # 6, 1 ImageFilter\n"; + EXPECTED_DUMP + += " (0018,9322) FD 0.1\\0.1 # 16, 2 ReconstructionPixelSpacing\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9321) SQ (Sequence with explicit length #=1) # 0, 1 CTExposureSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=10) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,115e) DS [0.5] # 4, 1 " + "ImageAndFluoroscopyAreaDoseProduct\n"; + EXPECTED_DUMP + += " (0018,1271) FD 0.6 # 8, 1 WaterEquivalentDiameter\n"; + EXPECTED_DUMP += " (0018,1272) SQ (Sequence with explicit length #=1) # 0, 1 " + "WaterEquivalentDiameterCalculationMethodCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [113987] # 6, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [AAPM 220] # 8, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9323) CS [WEIRD] # 6, 1 ExposureModulationType\n"; + EXPECTED_DUMP += " (0018,9324) FD 0.2 # 8, 1 EstimatedDoseSaving\n"; + EXPECTED_DUMP += " (0018,9328) FD 0.4 # 8, 1 ExposureTimeInms\n"; + EXPECTED_DUMP += " (0018,9330) FD 0.7 # 8, 1 XRayTubeCurrentInmA\n"; + EXPECTED_DUMP += " (0018,9332) FD 0.3 # 8, 1 ExposureInmAs\n"; + EXPECTED_DUMP += " (0018,9345) FD 0.1 # 8, 1 CTDIvol\n"; + EXPECTED_DUMP + += " (0018,9346) SQ (Sequence with explicit length #=1) # 0, 1 CTDIPhantomTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [113682] # 6, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [ACR Accreditation Phantom - CT] # 30, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9325) SQ (Sequence with explicit length #=1) # 0, 1 CTXRayDetailsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0060) DS [5] # 2, 1 KVP\n"; + EXPECTED_DUMP += " (0018,1160) SH [FILTER_TYPE] # 12, 1 FilterType\n"; + EXPECTED_DUMP += " (0018,1190) DS [4.4\\4.4\\4.4\\4.4] # 16, 4 FocalSpots\n"; + EXPECTED_DUMP += " (0018,7050) CS [FILTER_MATERIAL] # 16, 1 FilterMaterial\n"; + EXPECTED_DUMP + += " (0018,9351) FL 2 # 4, 1 CalciumScoringMassFactorPatient\n"; + EXPECTED_DUMP += " (0018,9352) FL 1\\1\\1 # 12, 3 " + "CalciumScoringMassFactorDevice\n"; + EXPECTED_DUMP += " (0018,9353) FL 3 # 4, 1 EnergyWeightingFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9326) SQ (Sequence with explicit length #=1) # 0, 1 CTPositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9313) FD 2\\2\\2 # 24, 3 DataCollectionCenterPatient\n"; + EXPECTED_DUMP += " (0018,9318) FD 1\\1\\1 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + EXPECTED_DUMP += " (0018,9327) FD 100 # 8, 1 TablePosition\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9329) SQ (Sequence with explicit length #=1) # 0, 1 CTImageFrameTypeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,9007) CS [ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM] # 32, 4 FrameType\n"; + EXPECTED_DUMP += " (0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + EXPECTED_DUMP += " (0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + EXPECTED_DUMP + += " (0008,9207) CS [VOLUME_RENDER] # 14, 1 VolumeBasedCalculationTechnique\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0018,9360) SQ (Sequence with explicit length #=1) # 0, 1 CTAdditionalXRaySourceSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=8) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0060) DS [5] # 2, 1 KVP\n"; + EXPECTED_DUMP + += " (0018,0090) DS [1] # 2, 1 DataCollectionDiameter\n"; + EXPECTED_DUMP += " (0018,1160) SH [FILTER_TYPE] # 12, 1 FilterType\n"; + EXPECTED_DUMP += " (0018,1190) DS [4.4\\4.4\\4.4\\4.4] # 16, 4 FocalSpots\n"; + EXPECTED_DUMP += " (0018,7050) CS [FILTER_MATERIAL] # 16, 1 FilterMaterial\n"; + EXPECTED_DUMP += " (0018,9330) FD 6 # 8, 1 XRayTubeCurrentInmA\n"; + EXPECTED_DUMP += " (0018,9332) FD 3 # 8, 1 ExposureInmAs\n"; + EXPECTED_DUMP += " (0018,9353) FL 2 # 4, 1 EnergyWeightingFactor\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0018,9477) SQ (Sequence with explicit length #=1) # 0, 1 " + "IrradiationEventIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0008,3010) UI [2.25.30853892236613436472911970638347155062] # 44, 1 IrradiationEventUID\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9071) SQ (Sequence with explicit length #=1) # 0, 1 FrameAnatomySequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0008,2218) SQ (Sequence with explicit length #=1) # 0, 1 AnatomicRegionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [12738006] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Brain] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP + += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP + += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9072) CS [B] # 2, 1 FrameLaterality\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9113) SQ (Sequence with explicit length #=1) # 0, 1 PlanePositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0032) DS [0.0\\0.0\\0.0] # 12, 3 ImagePositionPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9116) SQ (Sequence with explicit length #=1) # 0, 1 PlaneOrientationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0037) DS [1.0\\0.0\\0.0\\0.0\\1.0\\0.0] # 24, 6 ImageOrientationPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9310) SQ (Sequence with explicit length #=1) # 0, 1 TemporalPositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,930d) FD 1 # 8, 1 TemporalPositionTimeOffset\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0028,9110) SQ (Sequence with explicit length #=1) # 0, 1 PixelMeasuresSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0050) DS [1.0] # 4, 1 SliceThickness\n"; + EXPECTED_DUMP += " (0018,0088) DS [0.05] # 4, 1 SpacingBetweenSlices\n"; + EXPECTED_DUMP += " (0028,0030) DS [0.1\\0.1] # 8, 2 PixelSpacing\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0028,9132) SQ (Sequence with explicit length #=1) # 0, 1 FrameVOILUTSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0028,1050) DS [1000] # 4, 1 WindowCenter\n"; + EXPECTED_DUMP += " (0028,1051) DS [2000] # 4, 1 WindowWidth\n"; + EXPECTED_DUMP + += " (0028,1055) LO [BRAIN] # 6, 1 WindowCenterWidthExplanation\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0028,9145) SQ (Sequence with explicit length #=1) # 0, 1 PixelValueTransformationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0028,1052) DS [0] # 2, 1 RescaleIntercept\n"; + EXPECTED_DUMP += " (0028,1053) DS [1] # 2, 1 RescaleSlope\n"; + EXPECTED_DUMP += " (0028,1054) LO [HU] # 2, 1 RescaleType\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += "(5200,9230) SQ (Sequence with explicit length #=2) # 0, 1 PerFrameFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 1 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 1 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\1 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 2 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\2 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(7fe0,0010) OW 0001\\0001\\0001\\0001\\0002\\0002\\0002\\0002 # 16, 1 PixelData\n"; +} + +static void checkCreatedObject(const OFString& ds_dump) +{ + OFBool dump_ok = (ds_dump == EXPECTED_DUMP); + OFCHECK(dump_ok); + if (!dump_ok) + { + CERR << "Dump produced: " << OFendl << ds_dump << OFendl; + CERR << "------------------------------------" << OFendl; + CERR << "Dump expected: " << OFendl << EXPECTED_DUMP << OFendl; + CERR << "------------------------------------" << OFendl; + } +} diff --git a/dcmect/tests/tests.cc b/dcmect/tests/tests.cc new file mode 100644 index 00000000..54a6ca02 --- /dev/null +++ b/dcmect/tests/tests.cc @@ -0,0 +1,27 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Main test program for dcmect + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftest.h" + +OFTEST_REGISTER(dcmect_huge_concat); +OFTEST_REGISTER(dcmect_roundtrip); +OFTEST_MAIN("dcmect") diff --git a/dcmfg/include/dcmtk/dcmfg/concatenationcreator.h b/dcmfg/include/dcmtk/dcmfg/concatenationcreator.h new file mode 100644 index 00000000..c97ad293 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/concatenationcreator.h @@ -0,0 +1,265 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for creating Concatenations + * + */ + +#ifndef CONCATENATIONCREATOR_H +#define CONCATENATIONCREATOR_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgdefine.h" + +/** Class for creating Concatenations from existing SOP Instances. + * As input, a user can either provide a full SOP Instance with Pixel Data + * attribute, or a SOP Instance plus separate pixel data as a vector of frame data. + * The input file is uncompressed if necessary and possible, and the resulting + * concatenation instances will also contain uncompressed pixel data. + * During conversion, the original source pixel data is held into memory and + * additionally one of the concatenation instances the moment it is being produced + * when calling writeNextInstance() (see below). + * The following workflow must be used to create a Concatenation: + *
    + *
  • Call to one of the setCfgInput() methods in order to set the concatenation + * source data, i.e. the SOP Instance that should be split into a number of + * concatenation instances.
  • + *
  • Call to other setCfg...() calls in order to set conversion options. For example + * the number of frames per concatenation instance produced can be configured by calling + * setCfgFramesPerInstance(). Per default, 25 frames per instance are being used.
  • + *
  • Call to one of the writeNextInstance() methods in order to write the next + * concatenation instance.
  • + *
  • Call to the load() method in order to load of the the Concatenations found + * during scan(). Selection is done via the Concatenations Concatenation UID. + * The result is made available as a single, merged dataset without Pixel Data attribute + * and a vector containing all frames of the merged instance.
  • + *
+ */ +class DCMTK_DCMFG_EXPORT ConcatenationCreator +{ + +public: + /** Constructor + */ + ConcatenationCreator(); + + /** Virtual destructor + */ + virtual ~ConcatenationCreator(); + + /** Set input dataset that should be split into a number of + * concatenation instances + * @param srcDataset The dataset to read from (must not be NULL) + * @param transferOwnership If OFTrue, the ConcatenationCreator class will + * free memory of the srcDataset after processing. + * @return EC_Normal if input is considered valid (up to now), error otherwise + */ + virtual OFCondition setCfgInput(DcmItem* srcDataset, OFBool transferOwnership); + + /** Set input dataset with separate pixel data that should be split + * into a number of concatenation instances. + * @param srcDataset The dataset to read from (must not be NULL and not contain + * the Pixel Data attribute (on main level) + * @param pixelData Raw buffer of source pixel data + * @param pixelDataLength Length of pixelData buffer in bytes + * @param transferOwnership If OFTrue, the ConcatenationCreator class will + * free memory of the srcDataset and pixelData after processing. + * @return EC_Normal if input is considered valid (up to now), error otherwise + */ + virtual OFCondition + setCfgInput(DcmItem* srcDataset, Uint8* pixelData, size_t pixelDataLength, OFBool transferOwnership); + + /** Set number of frames that should go into a single concatenation instance produced. + * The last concatenation instance might have less frames. This setting also + * directly determines the number of instances produced for a specific input. + * @param numFramesPerInstance The number of frames to be used for each instance + * (last instance may differ) + * @return EC_Normal if setting is ok, error otherwise + */ + virtual OFCondition setCfgFramesPerInstance(Uint32 numFramesPerInstance); + + /** Set the Instance Number that should be used in the concatenation instances produced. + * @param instanceNumber The Instance Number to be used + * @return OFTrue if Instance Number is acceptable, OFFalse otherwise + */ + virtual OFBool setCfgInstanceNumber(const OFString& instanceNumber); + + /** Write first/next concatenation instance + * @param dstDataset The dataset to write to + * @return EC_Normal if instance could be written, + * FG_EC_ConcatenationComplete error code if the last instance has already been written, + * other error otherwise. + */ + virtual OFCondition writeNextInstance(DcmItem& dstDataset); + + /** Write first/next concatenation instance to given filename + * @param fn The filename to write to + * @return EC_Normal if instance could be written, + * FG_EC_ConcatenationComplete error code if the last instance has already been written, + * other error otherwise. + */ + virtual OFCondition writeNextInstance(const OFFilename& fn); + + /** Get number of concatenation instances that will be produced. + * This can only be used after setCfgInput() was successful; otherwise + * it will always return 0. + * @return The number of instances that will be produced + */ + virtual size_t getNumInstances(); + +protected: + /** Check whether SOP Class of given dataset does allow Concatenation. + * Right now the Standard forbids Concatenations for: + *
    + *
  • Ophthalmic Tomography Image Storage
  • + *
  • Ophthalmic Optical Coherence Tomography B-scan Volume Analysis Storage
  • + *
+ * @param srcDataset The dataset to check SOP Class for + * @return OFTrue if Concatenation is permitted, OFFalse otherwise + */ + virtual OFBool checkSOPClass(DcmItem& srcDataset); + + /** Check whether color model (Photometric Interpretation) and planar configuration + * are acceptable. + * Right now this class supports the following color models: + *
    + *
  • RGB
  • + *
  • YBR_FULL
  • + *
  • MONOCHROME1
  • + *
  • MONOCHROME2
  • + *
+ * Also, only Planar Configuration=0 is supported (or empty value implicating + * the same plane configuration). + * @param srcDataset The dataset to check + * @return OFTrue if color model and planar configuration is permitted, OFFalse otherwise + */ + virtual OFBool checkColorModel(DcmItem& srcDataset); + + /** Insert Concatenation attributes into destination dataset. + * @param dstDataset The destination dataset to write to + * @param numFramesCurrentInstance The number of frames that will go into + * the dataset + * @return EC_Normal if setting worked, error otherwise + */ + virtual OFCondition setConcatenationAttributes(DcmItem& dstDataset, Uint32 numFramesCurrentInstance); + + /** Advance internal counters to next frame + * @return EC_Normal if there is a next frame, error otherwise + */ + virtual OFCondition goToNextFrame(); + + /** Return number of frames that must be written into current instance. + * Will be the same for each instance except (potentially) the last one. + * @return Number of frames + */ + virtual Uint32 numFramesCurrentDstInstance(); + + /** Configure class based on input/configuration settings, i.e. prepare for + * concatenation writing. + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition configureCommon(); + +private: + + /// Maximum number of instances that make up a Concatenation (=2^16-1=65535), + /// derived from attributes In-concatentation Number and In-concatenation Total Number + /// that only store 16 bit values (VR US). + static Uint16 const m_MAX_INSTANCES_PER_CONCATENATION; + + /// Maximum number of bytes for uncompressed pixel data (=2^32-2), derived from + /// 32 bit length field of Pixel Data attribute with even length being required. + static Uint32 const m_MAX_PIXEL_DATA_LENGTH; + + /// Flag denoting whether class is configured (i.e. configureCommon() has been called) + /// and ready for concatenation writing. + OFBool m_configured; + + /// Flag denoting whether source data (dataset and/with frame data) should be + /// deleted by this class (OFTrue) or not (OFFalse). Value is initially OFFalse + /// but a value must be provided in any case in setCfgInput(). + OFBool m_cfgTransferOwnership; + + /// Number of instances each concatenation instance should contain (last may differ) + /// as configured by the user using setCfgFramesPerInstance(). Default is 25. + Uint32 m_cfgNumFramesPerInstance; + + /// Number of bytes used for each frame (same in source instance and concatenation instances). + /// Default is 25. Can be set by setCfgFramesPerInstance(). + size_t m_numBytesFrame; + + /// Pointer to source dataset; will be modified during conversion (but content is restored + /// before the call to this class returns). + /// Once the ConcatenationCreator creator class goes out of scope or reset() is being called, + /// it is set to NULL. If m_cfgTransferOwnership is OFTrue, memory is freed by this class, too. + DcmItem* m_srcDataset; + + /// SOP Instance UID of source instance provided in setCfgInput() + OFString m_srcSOPInstanceUID; + + /// Pointer to source pixel data; will be modified during conversion (but content is restored + /// before the call to this class returns). + /// Once the ConcatenationCreator creator class goes out of scope or reset() is being called, + /// it is set to NULL. If m_cfgTransferOwnership is OFTrue, memory is freed by this class, too. + Uint8* m_srcPixelData; + + /// VR of pixel data extracted/derived from source dataset. EVR_OB and EVR_OW are supported. + /// Initially set to EVR_Unknown. + DcmEVR m_VRPixelData; + + /// Pointer to Per-Frame Functional Group Sequence of source dataset. Use to copy + /// per-frame items to concatenation instances as needed. + DcmSequenceOfItems* m_srcPerFrameFG; + + /// Number of frames in source instance. + Uint32 m_srcNumFrames; + + /// Number of instances to be produced for Concatenation. + /// This is limited to 16 bit since the attributes + /// In-concatentation Number and In-concatenation Total Number only + /// stores 16 bit values (VR US). + Uint16 m_dstNumInstances; + + /// Number of Frames per instance (cached) to be produced for + /// all frames (last frame may differ) + Uint32 m_dstNumFramesPerInstance; + + /// Number of Frames per instance (cached) to be produced for + /// last frame + Uint32 m_dstNumFramesLastInstance; + + /// Concatenation UID to be used in the concatenation instances. Automatically + /// created during conversion. + OFString m_dstConcatenationUID; + + /// Instance Number to be used in concatenation instances produced. Can be + /// configured using setCfgInstanceNumber(). + OFString m_dstInstanceNumber; + + /// Source frame that is used next in conversion + Uint16 m_currentSrcFrame; + + /// Per frame FG item that is used next in conversion + DcmItem* m_currentPerFrameItem; + + /// Next instance number that is about to be produced + Uint16 m_currentInstanceNum; +}; + +#endif // CONCATENATIONCREATOR_H diff --git a/dcmfg/include/dcmtk/dcmfg/concatenationloader.h b/dcmfg/include/dcmtk/dcmfg/concatenationloader.h new file mode 100644 index 00000000..1ba53cd8 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/concatenationloader.h @@ -0,0 +1,369 @@ +/* + * + * Copyright (C) 2019-2020, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for loading Concatenations + * + */ + +#ifndef CONCATENATIONLOADER_H +#define CONCATENATIONLOADER_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofmap.h" + +class DcmDataset; + +/** Class for scanning files for concatenations and if desired, load + * one of them. If successful, loading produces the merged SOP Instance + * as a single dataset plus its frames in a separate data structure. The following + * workflow must be used: + *
    + *
  • Call to one of the scan() methods.
  • + *
  • If scanning was successful, call getInfo() to get information about the + * concatenations found by scan(). getFailedFiles() will return those files + * who could not be read, do not provide Concatenation information or had other errors.
  • + *
  • Call to the load() method in order to load of the the Concatenations found + * during scan(). Selection is done via the Concatenations Concatenation UID. + * The result is made available as a single, merged dataset without Pixel Data attribute + * and a vector containing all frames of the merged instance.
  • + *
+ */ +class DCMTK_DCMFG_EXPORT ConcatenationLoader +{ + +public: + /// Structure representing information about a Concatenation, + /// consisting of its instances and common data. + struct DCMTK_DCMFG_EXPORT Info + { + /// Struct representing single SOP Instance being part of a Concatenation. + struct DCMTK_DCMFG_EXPORT Instance + { + /// Filename of concatenation instance + OFFilename m_Filename; + /// SOP Instance UID of concatenation instance + OFString m_sopInstanceUID; + /// Number of Frames extracted from concatenation instance + Uint32 m_NumberOfFrames; + /// In-Concatenation Number extracted from concatenation instance + Uint16 m_InConcatenationNumber; + + /** Virtual destructor, frees memory + */ + virtual ~Instance(); + + /** Default constructor + */ + Instance(); + }; + + /** Default constructor */ + Info(); + + /** Copy constructor + * @param rhs The Info to copy from + */ + Info(const Info& rhs); + + /** Assignment operator + * @param rhs The Info to copy from + * @return Reference to "this" object + */ + Info& operator=(const Info& rhs); + + /// List of instances that belong to this Concatenation + OFList m_Files; + + /// File that contains the source of this Concatenation, i.e. + /// the SOP Instance UID of Concatenation Source tag points to. + /// Might be empty if such file is not found during scanning. + OFFilename m_FileConatenationSource; + + /// Concatenation UID of this Concatenation, extracted from concatenation instances + OFString m_ConcatenationUID; + + /// SOP Instance UID of Concatenation Source, extracted from concatenation instances + OFString m_SourceUID; + + /// In-Concatenation Total Number, extracted from concatenation instances (optional in DICOM) + Uint16 m_inConcatTotalNumber; + + /// Total number of frames, i.e. the number of frames that make up this concatenation instance. + /// The number is computed by summing up the number of frames in instances found during scanning. + size_t m_NumTotalFrames; + + /// Patient ID extracted from concatenation instances + OFString m_PatientID; + + /// Study Instance UID extracted from concatenation instances + OFString m_StudyInstanceUID; + + /// Series Instance UID extracted from concatenation instances + OFString m_SeriesInstanceUID; + + /// SOP Class UID extracted from concatenation instances + OFString m_SOPClassUID; + + /// Bits Allocated extracted from concatenation instances + Uint16 m_BitsAlloc; + + /// Rows extracted from concatenation instances + Uint16 m_Rows; + + /// Columns extracted from concatenation instances + Uint16 m_Cols; + + /** Print overview of this Concatenation + * @param out The stream to print to + */ + void print(OFStringStream& out); + + /** Virtual destructor + */ + virtual ~Info(); + }; + + /// structure representing error information about a failed file + struct DCMTK_DCMFG_EXPORT Failure + { + /// filename + OFFilename fname; + + /// error text + OFString errorText; + + /// SOP Instance UID + OFString sopInstance; + + /** constructor. + * @param fn filename + * @param err error text + * @param uid SOP instance UID + */ + Failure(const OFFilename& fn, const OFString& err, const OFString& uid) + : fname(fn), errorText(err), sopInstance(uid) {} + }; + + /// Result type of scan() + typedef OFMap TScanResult; + + /// Iterator type for iterating over scan() results + typedef OFMap::iterator ScanResultIt; + + /// Result type for the failures reported by scan() + typedef OFList TScanFailures; + + /// Result type for iterating the failures reported by scan() + typedef OFListIterator(Failure) TScanFailureIt; + + /** Constructor + */ + ConcatenationLoader(); + + /** Virtual destructor + */ + virtual ~ConcatenationLoader(); + + /** Ignore missing SOP Instance UID of Concatenation Source + * @param ignore If OFTrue, missing or empty SOP Instance UID of Concatenation Source tag is + * ignored and operation continues. + */ + virtual void setIgnoreMissingSourceUID(const OFBool ignore); + + /** Scan given list of files for Concatenations. If successful, a results + * can be accessed by calling getInfo() which contains an overview of the + * Concatenations found (and files that failed during reading). + * @param files The files to scan + * @return EC_Normal if scanning was successful, i.e. at least one Concatenation + * could be discovered successfully. + */ + virtual OFCondition scan(const OFList& files); + + /** Scan given directory for Concatenations. If successful, a results + * can be accessed by calling getInfo() which contains an overview of the + * Concatenations found (and files that failed during reading). + * @param directory The directory to scan + * @param pattern The search pattern (* per default) + * @param recursive If OFTrue, sub directories are scanned, too (default: OFTrue) + * @return EC_Normal if scanning was successful, i.e. at least one Concatenation + * could be discovered successfully. + */ + virtual OFCondition scan(const OFFilename& directory, const OFFilename& pattern = "*", OFBool recursive = OFTrue); + + /** Get successful results of scan() operation. Returns empty result set is scan() has + * not been called before. + * @return The results of the scan() operation + */ + virtual const TScanResult& getInfo(); + + /** Get failed files of scan() operation. Returns empty result set is scan() has + * not been called before (may be empty otherwise). + * @return The failed files of the scan() operation + */ + virtual const TScanFailures& getFailedFiles(); + + /** Load Concatenation and merge it into "original" source dataset. + * The Concatenation to be loaded is selected by its Concatenation UID. + * Frames are not written to the dataset's Pixel Data attribute but instead + * reside in a frame structure provided by the caller (since they could exceed + * the uncompressed maximum of 4 GB allowed in a single dataset). + * @param concatenationUID The Concatenation UID of the Concatenation + * to be loaded + * @param dataset The result dataset. The caller must hand in a pointer to + * a valid dataset, i.e. memory allocation must be done by the caller. + * During loading, the dataset must not be freed outside this class. + * However, the caller stays responsible to delete the dataset after usage. + * @param frames The resulting frames. Vector should provided empty by the user. + * The user is responsible for deleting frames after successful operation. + * If load() fails, this parameter should return an empty vector. + * @return EC_Normal if loading Concatenation worked, error otherwise. + */ + virtual OFCondition + load(const OFString& concatenationUID, DcmDataset* dataset, OFVector& frames); + +protected: + /** Handles single file of a Concatenation and extracts structure for later + * access by the user. + * @param file The file to process + * @param info The concatenation information structure to store results to + */ + virtual void handleFile(const OFFilename& file, ConcatenationLoader::Info& info); + + /** Checks an current file's information whether it fits to the rest of the + * Concatenation instances already read. If this is the case, the instance's + * information is added to the results. + * @param info Information for this Concatenation + * @param inst Instance information that should be added to the Concatenation + * @param error Error, if instance cannot be processed/added, otherwise empty. + */ + virtual void checkAndInsertInfo(const ConcatenationLoader::Info& info, + const ConcatenationLoader::Info::Instance& inst, + OFString& error); + + /** Check whether two numbers equal to 0 or empty. + * @param num1 The first number + * @param num2 The second number + * @return OFTrue if both number are equal or one of them is 0, OFFalse otherwise. + */ + virtual OFBool zeroOrEqual(const size_t num1, const size_t num2); + + /** Check whether two strings are equal or one of them is empty. + * @param str1 The first string + * @param str2 The second string + * @return OFTrue if both strings are equal or one of them is empty, OFFalse otherwise. + */ + virtual OFBool emptyOrEqual(const OFString& str1, const OFString& str2); + + /** Get that number from both which is not 0. + * @param num1 The first number + * @param num2 The second number + * @return num1 if num 1 is not zero, num 2 otherwise. + */ + template + T getNotZero(const T num1, const T num2); + + /** Perform consistency checks on the Concatenations found. + * @return EC_Normal if successful, failure otherwise + */ + virtual OFCondition doScanFinalChecks(); + + /** Prepare template (dataset) that is used to represent the final + * result dataset. + * @param firstInstance The first (or any instance) of the concatenation + * instances that will be used to create the result dataset. + * @return EC_Normal if successful, failure otherwise + */ + virtual OFCondition prepareTemplate(Info& firstInstance); + + /** Extract frames from given item. Works for Bits Allocated = 8 + * and Bits Allocated = 16. Resulting frames are stored + * in member variable. + * @param item The item to read Pixel Data attribute from + * @param info Concatenation information providing pixel meta data + * like Rows and Columns + * @param numFrames The number of frames to extract from item's + * Pixel Data attribute + * @return EC_Normal if extraction was successful, error otherwise. + */ + virtual OFCondition extractFrames(DcmItem& item, Info& info, Uint32 numFrames); + + /** Extract binary frames (Bits Allocated = 1) from given item. + * The resulting frames are stored in member variable. + * @param item The item to read Pixel Data attribute from + * @param info Concatenation information providing pixel meta data + * like Rows and Columns + * @param numFrames The number of frames to extract from item's + * Pixel Data attribute + * @return EC_Normal if extraction was successful, error otherwise. + */ + virtual OFCondition extractBinaryFrames(DcmItem& item, Info& info, Uint32 numFrames); + + /** Deletes those concatenation attributes from given item that are not + * used or get a different value in the resulting merged dataset. + * @param item The item to delete from + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition deleteConcatAttributes(DcmItem& item); + + /** Moves all Per-Frame Functional Group items found in given item + * to result instance. + * @param item The item to delete from + * @return EC_Normal if deletion was successful, error otherwise + */ + virtual OFCondition movePerFrameItems(DcmItem& item); + + /** Insert/adapt attributes that are required with the merged result + * instance. + * @return EC_Normal if successful, failure otherwise + */ + virtual OFCondition insertDestinationAttributes(); + + virtual OFCondition + computeBytesPerFrame(const Uint16 rows, const Uint16 cols, const Uint16 bitsAlloc, size_t& bytes_per_frame); + +private: + /// Map with entries consisting each of ConcatenationUID and related + /// Concatenation information. + TScanResult m_Concats; + + /// List with failed files, each entry consisting of filename, error text and + /// SOP Instance UID (latter might be empty). + TScanFailures m_FailedFiles; + + /// If OFTrue, the missing of attribute SOP Instance UID of Concatenation + /// Source is ignored and will not lead to an error + OFBool m_ignoreMissingSourceUID; + + /// The dataset that will contain the final merged SOP instance produced + /// by the load() method. Once a merged instance is provided to the caller, + /// as a result of load(), the caller is responsible for deleting the + /// related memory. + DcmDataset* m_Result; + + /// The frames that will contain all the frames of the merged SOP instance + /// produced by the load() method. Once a merged instance is provided to + /// the caller, as a result of load(), the caller is responsible for + /// deleting the related memory. + OFVector m_Frames; +}; + +#endif // CONCATENATIONLOADER_H diff --git a/dcmfg/include/dcmtk/dcmfg/fg.h b/dcmfg/include/dcmtk/dcmfg/fg.h index b240d0de..ddca09fe 100644 --- a/dcmfg/include/dcmtk/dcmfg/fg.h +++ b/dcmfg/include/dcmtk/dcmfg/fg.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,12 +23,12 @@ #define FG_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmap.h" -#include "dcmtk/dcmfg/fgtypes.h" -#include "dcmtk/dcmfg/fgbase.h" -#include "dcmtk/dcmdata/dctagkey.h" -#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofmap.h" // forward declaration class FGBase; @@ -40,75 +40,71 @@ class DCMTK_DCMFG_EXPORT FunctionalGroups { public: - - /// Iterator type for iterating functional groups - typedef OFMap::iterator iterator; - - /// Const iterator type for iterating functional groups - typedef OFMap::const_iterator const_iterator; - - /** Constructor, creates empty set of functional groups - */ - FunctionalGroups(); - - /** Virtual destructor, cleans up set of functional groups and - * frees the related memory - */ - virtual ~FunctionalGroups(); - - /** Cleans up set of functional groups and frees the related memory - */ - virtual void clear(); - - /** Find a functional group by its type - * @param fgType The type of the functional group - * @return The functional group, if found, NULL otherwise - */ - virtual FGBase* find(const DcmFGTypes::E_FGType fgType); - - /** Iterator pointing to first functional group in the set - * @return First functional group in set - */ - virtual FunctionalGroups::iterator begin(); - - /** Iterator pointing behind last functional group in the set - * @return Iterator pointing behind last functional group in the set - */ - virtual FunctionalGroups::iterator end(); - - /** Const iterator pointing to first functional group in the set - * @return First functional group in set - */ - virtual FunctionalGroups::const_iterator begin() const; - - /** Const iterator pointing behind last functional group in the set - * @return Iterator pointing behind last functional group in the set - */ - virtual FunctionalGroups::const_iterator end() const; - - /** Insert new functional group; ownership is taken over from caller if - * function call is successful. - * @param group The group to insert - * @param replaceOld If OFTrue, then the existing functional group of the - * same type (if existing) is deleted and replaced by the given one. - * @return EC_Normal, if insertion was successful, error otherwise. In the - * latter case, the caller keeps the ownership of the given object. - */ - virtual OFCondition insert(FGBase* group, - const OFBool replaceOld); - - /** Remove functional group specified by its type. The memory is not - * freed by the call but must freed by the caller using the returned pointer. - * @param fgType The type of the group to remove - * @return The functional group removed, or NULL, if not found - */ - virtual FGBase* remove(const DcmFGTypes::E_FGType fgType); + /// Iterator type for iterating functional groups + typedef OFMap::iterator iterator; + + /// Const iterator type for iterating functional groups + typedef OFMap::const_iterator const_iterator; + + /** Constructor, creates empty set of functional groups + */ + FunctionalGroups(); + + /** Virtual destructor, cleans up set of functional groups and + * frees the related memory + */ + virtual ~FunctionalGroups(); + + /** Cleans up set of functional groups and frees the related memory + */ + virtual void clear(); + + /** Find a functional group by its type + * @param fgType The type of the functional group + * @return The functional group, if found, NULL otherwise + */ + virtual FGBase* find(const DcmFGTypes::E_FGType fgType); + + /** Iterator pointing to first functional group in the set + * @return First functional group in set + */ + virtual FunctionalGroups::iterator begin(); + + /** Iterator pointing behind last functional group in the set + * @return Iterator pointing behind last functional group in the set + */ + virtual FunctionalGroups::iterator end(); + + /** Const iterator pointing to first functional group in the set + * @return First functional group in set + */ + virtual FunctionalGroups::const_iterator begin() const; + + /** Const iterator pointing behind last functional group in the set + * @return Iterator pointing behind last functional group in the set + */ + virtual FunctionalGroups::const_iterator end() const; + + /** Insert new functional group; ownership is taken over from caller if + * function call is successful. + * @param group The group to insert + * @param replaceOld If OFTrue, then the existing functional group of the + * same type (if existing) is deleted and replaced by the given one. + * @return EC_Normal, if insertion was successful, error otherwise. In the + * latter case, the caller keeps the ownership of the given object. + */ + virtual OFCondition insert(FGBase* group, const OFBool replaceOld); + + /** Remove functional group specified by its type. The memory is not + * freed by the call but must freed by the caller using the returned pointer. + * @param fgType The type of the group to remove + * @return The functional group removed, or NULL, if not found + */ + virtual FGBase* remove(const DcmFGTypes::E_FGType fgType); private: - - /// Map holding the functional groups, one of each type at most - OFMap m_groups; - + /// Map holding the functional groups, one of each type at most + OFMap m_groups; }; #endif // FG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgbase.h b/dcmfg/include/dcmtk/dcmfg/fgbase.h index 4d1645d9..6eaf395c 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgbase.h +++ b/dcmfg/include/dcmtk/dcmfg/fgbase.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,9 +23,10 @@ #define FGBASE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofstd.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofstd.h" /** Abstract base class for deriving specific functional groups */ @@ -33,125 +34,128 @@ class DCMTK_DCMFG_EXPORT FGBase { public: - - /** Constructor, creates new functional group of given type. - * @param fgType The type of functional group to create - */ - FGBase(const DcmFGTypes::E_FGType fgType); - - /** Check whether functional group has valid and complete data - * @return EC_Normal, if check is ok, error otherwise - */ - virtual OFCondition check() const = 0; - - /** Read functional group from given item. Old data is overwritten. - * @param item The item to read from. This must contain the sequence - * element that uniquely identifies the functional group. - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item) = 0; - - /** Write functional group to given item. If the functional group already - * exists it is overwritten. - * @param item The item to write to. The method will write the sequence - * specific for the functional group into the item - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item) = 0; - - /** Find out whether functional group is potentially only shared, only - * per-frame or can be both - * @return The functional group "shared type" - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const =0; - - /** Return the type of this functional group - * @return The functional group's type - */ - virtual DcmFGTypes::E_FGType getType() const; - - /** Clear any data in the group - */ - virtual void clearData() =0; - - /** Virtual destructor - */ - virtual ~FGBase(); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (e.g.\ both - * FGDerivationImage) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const FGBase& rhs) const = 0; - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const = 0; + /** Constructor, creates new functional group of given type. + * @param fgType The type of functional group to create + */ + FGBase(const DcmFGTypes::E_FGType fgType); + + /** Check whether functional group has valid and complete data + * @return EC_Normal, if check is ok, error otherwise + */ + virtual OFCondition check() const = 0; + + /** Read functional group from given item. Old data is overwritten. + * @param item The item to read from. This must contain the sequence + * element that uniquely identifies the functional group. + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item) = 0; + + /** Write functional group to given item. If the functional group already + * exists it is overwritten. + * @param item The item to write to. The method will write the sequence + * specific for the functional group into the item + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item) = 0; + + /** Find out whether functional group is potentially only shared, only + * per-frame or can be both + * @return The functional group "shared type" + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const = 0; + + /** Return the type of this functional group + * @return The functional group's type + */ + virtual DcmFGTypes::E_FGType getType() const; + + /** Clear any data in the group + */ + virtual void clearData() = 0; + + /** Virtual destructor + */ + virtual ~FGBase(); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (e.g.\ both + * FGDerivationImage) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const = 0; + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const = 0; protected: - - /** Get the item containing the payload of a functional group sequence, - * identified by the functional group's sequence key provided and the desired - * item number. - * @param source The item to read the sequence from, e.g.\ item of the - * Shared Functional Group Sequence - * @param seqKey The identifying key of the functional group's sequence - * @param itemNum The item number to get from that sequence (usually, - * a functional group has exactly a single item, i.e.\ the parameter - * would be set to 0 - * @param result The item if found, otherwise NULL - * @return EC_Normal, if specified item could be retrieved, error otherwise - */ - virtual OFCondition getItemFromFGSequence(DcmItem& source, + /** Get the item containing the payload of a functional group sequence, + * identified by the functional group's sequence key provided and the desired + * item number. + * @param source The item to read the sequence from, e.g.\ item of the + * Shared Functional Group Sequence + * @param seqKey The identifying key of the functional group's sequence + * @param itemNum The item number to get from that sequence (usually, + * a functional group has exactly a single item, i.e.\ the parameter + * would be set to 0 + * @param result The item if found, otherwise NULL + * @return EC_Normal, if specified item could be retrieved, error otherwise + */ + virtual OFCondition + getItemFromFGSequence(DcmItem& source, const DcmTagKey& seqKey, const unsigned long itemNum, DcmItem*& result); + + /** Get number of items in a functional group sequence, identified by the functional + * group's sequence key. + * @param source The item to read the sequence from, e.g.\ item of the + * Shared Functional Group Sequence + * @param seqKey The identifying key of the functional group's sequence + * @param result The number of items found + * @return EC_Normal, if number could be retrieved, error otherwise + */ + virtual OFCondition getNumItemsFromFGSequence(DcmItem& source, const DcmTagKey& seqKey, unsigned long& result); + + /** Create functional group sequence specified by given sequence tag key + * @param destination The item to put the sequence into + * @param seqKey The functional group's tag key + * @param numItems The number of items to create within sequence (minus 1). + * Usually, functional group only contain a single item, + * i.e.\ numItems would be set to 0 + * @param firstItem Reference to the first item the method created + * @return EC_Normal if creation was successful, error otherwise + */ + virtual OFCondition createNewFGSequence(DcmItem& destination, const DcmTagKey& seqKey, - const unsigned long itemNum, - DcmItem*& result); - - /** Create functional group sequence specified by given sequence tag key - * @param destination The item to put the sequence into - * @param seqKey The functional group's tag key - * @param numItems The number of items to create within sequence (minus 1). - * Usually, functional group only contain a single item, - * i.e.\ numItems would be set to 0 - * @param firstItem Reference to the first item the method created - * @return EC_Normal if creation was successful, error otherwise - */ - virtual OFCondition createNewFGSequence(DcmItem& destination, - const DcmTagKey& seqKey, - const unsigned long numItems, - DcmItem*& firstItem); + const unsigned long numItems, + DcmItem*& firstItem); private: + /// Private default constructor, shall not be used + FGBase(); - /// Private default constructor, shall not be used - FGBase(); - - /// The type of the functional group - DcmFGTypes::E_FGType m_fgType; - + /// The type of the functional group + DcmFGTypes::E_FGType m_fgType; }; - /** Class representing an "unknown" functional group, e.g.\ a private one * specified by a vendor or one that is not explicitly known yet to the * dcmfg library. @@ -163,107 +167,110 @@ class DCMTK_DCMFG_EXPORT FGUnknown : public FGBase { public: - - /** Creates unknown (to the dcmfg class library) functional group - * @param seqStartTag The tag that uniquely identifies this functional group - * @param sharedType Defines whether this group is potentially per-frame, - * shared or can be both. Default is "unknown". - */ - FGUnknown(const DcmTagKey& seqStartTag, - const DcmFGTypes::E_FGSharedType sharedType = DcmFGTypes::EFGS_UNKNOWN); - - /** Copy constructor, performs a deep copy of the given object. - * @param rhs The functional group to initialize from - */ - FGUnknown(const FGUnknown& rhs); - - /** Assignment operator, performs a deep copy for assigning given object. - * @param rhs The functional group to assign from - * @return Reference to this object - */ - FGUnknown& operator=(const FGUnknown& rhs); - - /** Returns type of this functional group (always "EFG_UNKNOWN") - * @return Always returns DcmFGTypes::EFG_UNKNOWN - */ - virtual DcmFGTypes::E_FGType getType() const {return DcmFGTypes::EFG_UNKNOWN;} - - /** Returns whether this group is potentially per-frame, shared or can be both - * @return The functional group's "shared type" - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return m_sharedType;} - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Check whether this functional group contains valid data - * @returns EC_Normal if functional group is valid. For now, always returns - * EC_Normal - */ - virtual OFCondition check() const; - - /** Clear data within this group - */ - virtual void clearData(); - - /** Read this group into memory - * @param item The item to read from - */ - virtual OFCondition read(DcmItem& item); - - /** Write this group to given item - * @param item The item to write to - */ - virtual OFCondition write(DcmItem& item); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - /** Virtual destructor, frees memory - */ - virtual ~FGUnknown(); + /** Creates unknown (to the dcmfg class library) functional group + * @param seqStartTag The tag that uniquely identifies this functional group + * @param sharedType Defines whether this group is potentially per-frame, + * shared or can be both. Default is "unknown". + */ + FGUnknown(const DcmTagKey& seqStartTag, const DcmFGTypes::E_FGSharedType sharedType = DcmFGTypes::EFGS_UNKNOWN); + + /** Copy constructor, performs a deep copy of the given object. + * @param rhs The functional group to initialize from + */ + FGUnknown(const FGUnknown& rhs); + + /** Assignment operator, performs a deep copy for assigning given object. + * @param rhs The functional group to assign from + * @return Reference to this object + */ + FGUnknown& operator=(const FGUnknown& rhs); + + /** Returns type of this functional group (always "EFG_UNKNOWN") + * @return Always returns DcmFGTypes::EFG_UNKNOWN + */ + virtual DcmFGTypes::E_FGType getType() const + { + return DcmFGTypes::EFG_UNKNOWN; + } + + /** Returns whether this group is potentially per-frame, shared or can be both + * @return The functional group's "shared type" + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return m_sharedType; + } + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Check whether this functional group contains valid data + * @returns EC_Normal if functional group is valid. For now, always returns + * EC_Normal + */ + virtual OFCondition check() const; + + /** Clear data within this group + */ + virtual void clearData(); + + /** Read this group into memory + * @param item The item to read from + * @return EC_Normal if reading was successful, error code otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write this group to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error code otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Virtual destructor, frees memory + */ + virtual ~FGUnknown(); private: + /** Private default constructor, shall not be used + */ + FGUnknown(); - /** Private default constructor, shall not be used - */ - FGUnknown(); + /// The tag that uniquely identifies this functional group + DcmTagKey m_seqStartTag; - /// The tag that uniquely identifies this functional group - DcmTagKey m_seqStartTag; - - /// The data hold by this item, i.e.\ the sequence making up the functional - /// group - DcmSequenceOfItems* m_fgSequence; - - /// Denotes whether this group is potentially per-frame, shared or can be both - DcmFGTypes::E_FGSharedType m_sharedType; + /// The data hold by this item, i.e.\ the sequence making up the functional + /// group + DcmSequenceOfItems* m_fgSequence; + /// Denotes whether this group is potentially per-frame, shared or can be both + DcmFGTypes::E_FGSharedType m_sharedType; }; #endif // FGBASE_H - diff --git a/dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h b/dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h new file mode 100644 index 00000000..3957293e --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h @@ -0,0 +1,373 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Acquisition Details Functional Group + * + */ + +#ifndef FGCTACQUISITIONDETAILS_H +#define FGCTACQUISITIONDETAILS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Acquisition Details" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTAcquisitionDetails : public FGBase +{ +public: + enum E_RotationDirection + { + E_RotationDirection_CC, + E_RotationDirection_CW, + E_RotationDirection_Empty, + E_RotationDirection_Invalid + }; + + /** Constructor, creates empty functional group + */ + FGCTAcquisitionDetails(); + + /** Class representing an item of the "CT Acquisition Details " Functional Group Macro. + */ + class DCMTK_DCMFG_EXPORT FGCTAcquisitionDetailsItem + { + public: + /** Constructor + */ + FGCTAcquisitionDetailsItem(); + + /** Virtual destructor + */ + virtual ~FGCTAcquisitionDetailsItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTAcquisitionDetailsItem* clone() const; + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Acquisition Details Sequence item from given dataitem + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Acquisition Details Sequence item + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTAcquisitionDetailsItem& rhs) const; + + // --- get() functionality --- + + /** Get Referenced Path Index + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(Uint16& value, const unsigned long pos = 0); + + /** Get Referenced Path Index + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFVector& values); + + /** Get Rotation Direction + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRotationDirection(OFString& value, const signed long pos = 0); + + /** Get Rotation Direction + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRotationDirection(E_RotationDirection& value, const signed long pos = 0); + + /** Get Revolution Time + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRevolutionTime(Float64& value, const unsigned long pos = 0); + + /** Get Single Collimation Width + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getSingleCollimationWidth(Float64& value, const unsigned long pos = 0); + + /** Get Total Collimation Width + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTotalCollimationWidth(Float64& value, const unsigned long pos = 0); + + /** Get Table Height + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTableHeight(Float64& value, const unsigned long pos = 0); + + /** Get Gantry Detector Tilt + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getGantryDetectorTilt(Float64& value, const unsigned long pos = 0); + + /** Get Data Collection Diameter + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDataCollectionDiameter(Float64& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Referenced Path Index + * @param values Values that should be set + * @param checkValues Check 'values'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReferencedPathIndex(const OFVector& values, const OFBool checkValues = OFTrue); + + /** Set Rotation Direction + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setRotationDirection(const E_RotationDirection& value, const OFBool checkValue = OFTrue); + + /** Set Revolution Time + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setRevolutionTime(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Single Collimation Width + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setSingleCollimationWidth(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Total Collimation Width + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTotalCollimationWidth(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Table Height + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTableHeight(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Gantry/Detector Tilt + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setGantryDetectorTilt(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Data Collection Diameter + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setDataCollectionDiameter(const Float64 value, const OFBool checkValue = OFTrue); + + static E_RotationDirection rotaDir2Enum(const OFString& str); + + static OFBool rotaDir2Str(const E_RotationDirection& rota, OFString& result); + + private: + /* Content of CT Acquisition Details Macro (item) */ + + /// Referenced Path Index (US, VM 1-n, Required type 1C) + DcmUnsignedShort m_ReferencedPathIndex; + + /// Rotation Direction (CS, 1, 1C) + DcmCodeString m_RotationDirection; + + /// Revolution Time (FD, 1, 1C) + DcmFloatingPointDouble m_RevolutionTime; + + /// Single Collimation Width (FD, 1, 1C) + DcmFloatingPointDouble m_SingleCollimationWidth; + + /// Total Collimation Width (FD, 1, 1C) + DcmFloatingPointDouble m_TotalCollimationWidth; + + /// Table Height (DS, 1, 1C) + DcmDecimalString m_TableHeight; + + /// Gantry/Detector Tilt (DS, 1, 1C) + DcmDecimalString m_GantryDetectorTilt; + + /// Data Collection Diameter (DS, 1, 1C) + DcmDecimalString m_DataCollectionDiameter; + }; + + /** Virtual destructor + */ + virtual ~FGCTAcquisitionDetails(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Acquisition Details Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Acquisition Details Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + OFVector& getCTAcquisitionDetailsItems(); + +private: + /* Content of CT Acquisition Details Macro */ + + OFVector m_Items; +}; + +#endif // FGCTACQUISITIONDETAILS_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h b/dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h new file mode 100644 index 00000000..084cb092 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h @@ -0,0 +1,247 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Acquisition Type Functional Group + * + */ + +#ifndef FGCTACQUISITIONTYPE_H +#define FGCTACQUISITIONTYPE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Acquisition Type" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTAcquisitionType : public FGBase +{ +public: + static const OFString DT_AcquisitionType_Sequenced; + static const OFString DT_AcquisitionType_Spiral; + static const OFString DT_AcquisitionType_ConstantAngle; + static const OFString DT_AcquisitionType_Stationary; + static const OFString DT_AcquisitionType_Free; + + enum E_ConstantVolumeFlag + { + E_ConstVol_Yes, + E_ConstVol_No, + E_ConstVol_Empty, + E_ConstVol_Invalid + }; + + enum E_FluoroscopyFlag + { + E_Fluoroscopy_Yes, + E_Fluoroscopy_No, + E_Fluoroscopy_Empty, + E_Fluoroscopy_Invalid + }; + + /** Constructor, creates empty functional group + */ + FGCTAcquisitionType(); + + /** Virtual destructor + */ + virtual ~FGCTAcquisitionType(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Acquisition Type Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Acquisition Type Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Acquisition Type + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getAcquisitionType(OFString& value, const signed long pos = 0); + + /** Get Tube Angle + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTubeAngle(Float64& value, const unsigned long pos = 0); + + /** Get Constant Value Flag + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getConstantVolumeFlag(OFString& value, const signed long pos = 0); + + /** Get Constant Value Flag + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getConstantVolumeFlag(E_ConstantVolumeFlag& value, const signed long pos = 0); + + /** Get Fluoroscopy Flag + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFluoroscopyFlag(OFString& value, const signed long pos = 0); + + /** Get Fluoroscopy Flag + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFluoroscopyFlag(E_FluoroscopyFlag& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Acquisition Type + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setAcquisitionType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Tube Angle + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTubeAngle(const Float64& value, const OFBool checkValue = OFTrue); + + /** Set Constant Volume Flag + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setConstantVolumeFlag(const E_ConstantVolumeFlag& value, const OFBool checkValue = OFTrue); + + /** Set Constant Volume Flag + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setConstantVolumeFlag(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Fluoroscopy Flag + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFluoroscopyFlag(const E_FluoroscopyFlag& value, const OFBool checkValue = OFTrue); + + /** Set Fluoroscopy Flag + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFluoroscopyFlag(const OFString& value, const OFBool checkValue = OFTrue); + + static E_ConstantVolumeFlag constVolFlag2Enum(const OFString& str); + + static OFBool constVolFlag2Str(const E_ConstantVolumeFlag& eval, OFString& result); + + static E_FluoroscopyFlag fluoroscopyFlag2Enum(const OFString& str); + + static OFBool fluoroscopyFlag2Str(const E_FluoroscopyFlag& eval, OFString& result); + +private: + /* Content of CT Acquisition Type Macro */ + + /// Acquisition Type (CS, VM 1, Required type 1) + DcmCodeString m_AcquisitionType; + + /// Tube Angle (FD, 1, 1) + DcmFloatingPointDouble m_TubeAngle; + + /// Constant Volume Flag (CS, 1, 1) + DcmCodeString m_ConstantVolumeFlag; + + /// Fluoroscopy Flag (CS, 1, 1) + DcmCodeString m_FluoroscopyFlag; +}; + +#endif // FGCTACQUISITIONTYPE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h b/dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h new file mode 100644 index 00000000..9d2ab441 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h @@ -0,0 +1,371 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Additional X-Ray Source Functional Group + * + */ + +#ifndef FGCTADDITIONALXRAYSOURCE_H +#define FGCTADDITIONALXRAYSOURCE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dctk.h" // TODO: include only needed VRs +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmfg/fgdefine.h" + +/** Class representing the CT Additional X-Ray Source Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTAdditionalXRaySource : public FGBase +{ +public: + /** Constructor, creates empty CT Additional X-Ray Source Functional Group + */ + FGCTAdditionalXRaySource(); + + /** Destructor, frees memory + */ + virtual ~FGCTAdditionalXRaySource(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Clears all data + */ + virtual void clearData(); + + /** Read functional group from given item, i.e.\ read CT Additional X-Ray Source Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write CT Additional X-Ray Source Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Class representing an item of the "CT Additional X-Ray Source" Functional Group Macro. + */ + class DCMTK_DCMFG_EXPORT FGCTAdditionalXRaySourceItem + { + public: + /** Constructor, creates empty CT Additional X-Ray Source Functional Group + */ + FGCTAdditionalXRaySourceItem(); + + /** Destructor, frees memory + */ + virtual ~FGCTAdditionalXRaySourceItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTAdditionalXRaySourceItem* clone() const; + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read CT Additional X-Ray Source Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write CT Additional X-Ray Source Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get KVP + * Peak kilo voltage output of the X-Ray generator used. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getKVP(OFString& value, const signed long pos = 0) const; + + /** Get XRayTubeCurrentInmA + * Nominal X-Ray tube current in milliamperes. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getXRayTubeCurrentInmA(Float64& value, const unsigned long pos = 0) const; + + /** Get DataCollectionDiameter + * The diameter in mm of the region over which data were collected. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDataCollectionDiameter(OFString& value, const signed long pos = 0) const; + + /** Get FocalSpots + * Used nominal size of the focal spot in mm. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFocalSpots(OFString& value, const signed long pos = 0) const; + + /** Get FilterType + * Type of filter(s) inserted into the X-Ray beam. See + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFilterType(OFString& value, const signed long pos = 0) const; + + /** Get FilterMaterial + * The X-Ray absorbing material used in the filter. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFilterMaterial(OFString& value, const signed long pos = 0) const; + + /** Get ExposureInmAs + * The exposure expressed in milliampere seconds, for example calculated from exposure time and X-Ray tube + * current. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getExposureInmAs(Float64& value, const unsigned long pos = 0) const; + + /** Get EnergyWeightingFactor + * The weighting factor of the data from this additional source in a multiple energy composition image. This + * factor incorporates the effects ofRequired if Required if Frame Type (0008,9007) Value 4 of this frame is + * ENERGY_PROP_WT. May be present otherwise. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getEnergyWeightingFactor(Float32& value, const unsigned long pos = 0) const; + + /** Set KVP + * Peak kilo voltage output of the X-Ray generator used. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setKVP(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set KVP + * Peak kilo voltage output of the X-Ray generator used. + * @param value Value to be set + * @param checkValue Check 'value' if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setKVP(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set XRayTubeCurrentInmA + * Nominal X-Ray tube current in milliamperes. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setXRayTubeCurrentInmA(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set DataCollectionDiameter + * The diameter in mm of the region over which data were collected. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDataCollectionDiameter(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set DataCollectionDiameter + * The diameter in mm of the region over which data were collected. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDataCollectionDiameter(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set FocalSpots + * Used nominal size of the focal spot in mm. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFocalSpots(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set FocalSpots + * Used nominal size of the focal spot in mm. + * @param values Values to be set + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFocalSpots(const OFVector& values, const OFBool checkValue = OFTrue); + + /** Set FilterType + * Type of filter(s) inserted into the X-Ray beam. See + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFilterType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set FilterMaterial + * The X-Ray absorbing material used in the filter. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFilterMaterial(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set ExposureInmAs + * The exposure expressed in milliampere seconds, for example calculated from exposure time and X-Ray tube + * current. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setExposureInmAs(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set EnergyWeightingFactor + * The weighting factor of the data from this additional source in a multiple energy composition image. This + * factor incorporates the effects ofRequired if Required if Frame Type (0008,9007) Value 4 of this frame is + * ENERGY_PROP_WT. May be present otherwise. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (FL) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setEnergyWeightingFactor(const Float32 value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTAdditionalXRaySourceItem& rhs) const; + + protected: + /* Content of CT Additional X-Ray Source Functional Group Macro */ + + /// KVP (DS, VM 1, Required type 1) + /// Peak kilo voltage output of the X-Ray generator used. + DcmDecimalString m_KVP; + + /// XRayTubeCurrentInmA (FD, VM 1, Required type 1) + /// Nominal X-Ray tube current in milliamperes. + DcmFloatingPointDouble m_XRayTubeCurrentInmA; + + /// DataCollectionDiameter (DS, VM 1, Required type 1) + /// The diameter in mm of the region over which data were collected. + DcmDecimalString m_DataCollectionDiameter; + + /// FocalSpots (DS, VM 1-n, Required type 1) + /// Used nominal size of the focal spot in mm. + DcmDecimalString m_FocalSpots; + + /// FilterType (SH, VM 1, Required type 1) + /// Type of filter(s) inserted into the X-Ray beam. See + DcmShortString m_FilterType; + + /// FilterMaterial (CS, VM 1-n, Required type 1) + /// The X-Ray absorbing material used in the filter. + DcmCodeString m_FilterMaterial; + + /// ExposureInmAs (FD, VM 1, Required type 1) + /// The exposure expressed in milliampere seconds, for example calculated from exposure time and X-Ray tube + /// current. + DcmFloatingPointDouble m_ExposureInmAs; + + /// EnergyWeightingFactor (FL, VM 1, Required type 1C) + /// The weighting factor of the data from this additional source in a multiple energy composition image. This + /// factor incorporates the effects ofRequired if Required if Frame Type (0008,9007) Value 4 of this frame is + /// ENERGY_PROP_WT. May be present otherwise. + DcmFloatingPointSingle m_EnergyWeightingFactor; + }; + + virtual OFVector& getCTAdditionalXRaySourceItems(); + +protected: + OFVector m_Items; +}; + +#endif // FGCTADDITIONALXRAYSOURCE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctexposure.h b/dcmfg/include/dcmtk/dcmfg/fgctexposure.h new file mode 100644 index 00000000..18f2034b --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctexposure.h @@ -0,0 +1,419 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Exposure Functional Group + * + */ + +#ifndef FGCTEXPOSURE_H +#define FGCTEXPOSURE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Exposure" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTExposure : public FGBase +{ +public: + /** Constructor, creates empty functional group + */ + FGCTExposure(); + + /** Copy Constructor, creates deep copy + * @param rhs The object to copy from + */ + FGCTExposure(const FGCTExposure& rhs); + + /** Virtual destructor + */ + virtual ~FGCTExposure(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Exposure Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Exposure Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Class representing the "CT Exposure" Functional Group Macro item + */ + class DCMTK_DCMFG_EXPORT FGCTExposureItem + { + public: + /** Constructor, creates empty functional group item + */ + FGCTExposureItem(); + + /** Copy Constructor, creates deep copy + * @param rhs The object to copy from + */ + FGCTExposureItem(const FGCTExposureItem& rhs); + + /** Virtual destructor + */ + virtual ~FGCTExposureItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTExposureItem* clone() const; + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Exposure Sequence item from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTExposureItem& rhs) const; + + // --- get() functionality --- + + /** Get Referenced Path Index + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFString& value, const signed long pos = 0); + + /** Get Exposure Time in ms + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getExposureTimeInMs(OFString& value, const signed long pos = 0); + + /** Get Exposure Time in ms + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getExposureTimeInMs(Float64& value, const unsigned long pos = 0); + + /** Get X-Ray Tube Current in mA + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getXRayTubeCurrentInMa(OFString& value, const signed long pos = 0); + + /** Get X-Ray Tube Current in mA + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getXRayTubeCurrentInMa(Float64& value, const unsigned long pos = 0); + + /** Get Exposure in mAs + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getExposureInMas(OFString& value, const signed long pos = 0); + + /** Get Exposure in mAs + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getExposureInMas(Float64& value, const unsigned long pos = 0); + + /** Get Exposure Modulation Type + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getExposureModulationType(OFString& value, const signed long pos = 0); + + /** Get Estimated Dose Saving + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getEstimatedDoseSaving(OFString& value, const signed long pos = 0); + + /** Get Estimated Dose Saving + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getEstimatedDoseSaving(Float64& value, const unsigned long pos = 0); + + /** Get CTDIvol + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCTDIVol(OFString& value, const signed long pos = 0); + + /** Get CTDIvol + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCTDIVol(Float64& value, const unsigned long pos = 0); + + virtual OFVector& getCTDIPhantomTypeCodeSequence(); + + /** Get Water Equivalent Diameter + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getWaterEquivalentDiameter(OFString& value, const signed long pos = 0); + + /** Get Water Equivalent Diameter + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getWaterEquivalentDiameter(Float64& value, const unsigned long pos = 0); + + virtual OFVector& getWaterEquivalentDiameterCalculationMethodCodeSequence(); + + /** Get Image And Fluoroscopy Area Dose Product + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getImageAndFluoroscopyAreaDoseProduct(OFString& value, const signed long pos = 0); + + /** Get Image And Fluoroscopy Area Dose Product + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getImageAndFluoroscopyAreaDoseProduct(Float64& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Referenced Path Index + * @param values Values that should be set + * @param checkValues If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReferencedPathIndex(const OFVector& values, const OFBool checkValues = OFTrue); + + /** Set Exposure Time in ms + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setExposureTimeInMs(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set X-Ray Tube Current In Ma + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setXRayTubeCurrentInMa(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Exposure in mAs + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setExposureInMas(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Exposure Modulation Type + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setExposureModulationType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Estimated Dose Saving + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setEstimatedDoseSaving(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set CTDIVol + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setCTDIVol(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Water Equivalent Diameter + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setWaterEquivalentDiameter(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Image and Fluoroscopy Area Dose Product + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setImageAndFluoroscopyAreaDoseProduct(const Float64 value, + const OFBool checkValue = OFTrue); + + private: + /* Content of CT Exposure Macro item */ + + /// Referenced Path Index (US, VM 1-n, Required type 1C) + DcmUnsignedShort m_ReferencedPathIndex; + + /// Exposure Time in ms (FD, 1, 1C) + DcmFloatingPointDouble m_ExposureTimeInMs; + + /// X-Ray Tube Current in mA (FD, 1, 1C) + DcmFloatingPointDouble m_XRayTubeCurrentInMa; + + /// Exposure in mAs (FD, 1, 1C) + DcmFloatingPointDouble m_ExposureInMas; + + /// Exposure Modulation Type (CS, 1-n, 1C) + DcmCodeString m_ExposureModulationType; + + /// Estimated Dose Saving (FD, 1, 2C) + DcmFloatingPointDouble m_EstimatedDoseSaving; + + /// CTDIvol (FD, 1, 2C) + DcmFloatingPointDouble m_CTDIVol; + + /// CTDI Phantom Type Code Sequence (SQ, 1, 3) + OFVector m_CTDIPhantomTypeCodeSequence; + + /// Water Equivalent Diameter (FD, 1, 3) + DcmFloatingPointDouble m_WaterEquivalentDiameter; + + /// Water Equivalent Diameter Calculation Method Code Sequence (SQ, 1, 1C) + OFVector m_WaterEquivalentDiameterCalculationMethodCodeSequence; + + /// Image and Fluoroscopy Area Dose Product (DS, 1, 3) + DcmDecimalString m_ImageAndFluoroscopyAreaDoseProduct; + }; + + OFVector& getCTExposureItems(); + +private: + /* Content of CT Exposure Macro */ + + /// Items of CT Exposure Macro + OFVector m_Items; +}; + +#endif // FGCTEXPOSURE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctgeometry.h b/dcmfg/include/dcmtk/dcmfg/fgctgeometry.h new file mode 100644 index 00000000..d6115533 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctgeometry.h @@ -0,0 +1,260 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Geometry Functional Group + * + */ + +#ifndef FGCTGEOMETRY_H +#define FGCTGEOMETRY_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Geometry" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTGeometry : public FGBase +{ +public: + /** Class representing the "CT Geometry" Functional Group Macro item + */ + class DCMTK_DCMFG_EXPORT FGCTGeometryItem + { + public: + /** Constructor, creates empty functional group + */ + FGCTGeometryItem(); + + /** Virtual destructor + */ + virtual ~FGCTGeometryItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTGeometryItem* clone() const; + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Geometry Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTGeometryItem& rhs) const; + + // --- get() functionality --- + + /** Get Referenced Path Index + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFString& value, const signed long pos = 0); + + /** Get Referenced Path Index + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFVector& values); + + /** Get Distance Source to Detector + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDistanceSourceToDetector(OFString& value, const signed long pos = 0); + + /** Get Distance Source to Detector + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDistanceSourceToDetector(Float64& value, const unsigned long pos = 0); + + /** Get Distance Source to Data Collection Center + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDistanceSourceToDataCollectionCenter(OFString& value, const signed long pos = 0); + + /** Get Distance Source to Data Collection Center + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDistanceSourceToDataCollectionCenter(OFVector& values); + + // --- set() functionality --- + + /** Set Referenced Path Index + * @param values Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReferencedPathIndex(const OFVector& values, const OFBool checkValue = OFTrue); + + /** Set Distance Source To Detector + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setDistanceSourceToDetector(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Distance Source To Data Collection Center + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setDistanceSourceToDataCollectionCenter(const Float64 value, + const OFBool checkValue = OFTrue); + + private: + /* Content of CT Geometry Macro */ + + /// Referenced Index Path (US, VM 1-n, Required type 1C) + DcmUnsignedShort m_ReferencedPathIndex; + + /// Distance Source To Detector (DS, 1, 1C) + DcmDecimalString m_DistanceSourceToDetector; + + /// Distance Source to Data Collection Center + DcmFloatingPointDouble m_DistanceSourceToDataCollectionCenter; + }; + + /** Constructor, creates empty functional group + */ + FGCTGeometry(); + + /** Virtual destructor + */ + virtual ~FGCTGeometry(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Geometry Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Geometry Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + OFVector& getCTGeometryItems(); + +private: + /* Content of CT Geometry Macro */ + + /// Items of this functional group macro + OFVector m_Items; +}; + +#endif // FGCTGEOMETRY_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h b/dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h new file mode 100644 index 00000000..43445578 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h @@ -0,0 +1,257 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Image Frame Type Functional Group + * + */ + +#ifndef FGCTIMAGEFRAMETYPE_H +#define FGCTIMAGEFRAMETYPE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Image Frame Type" Functional Group Macro. Can only be + * used as per-frame functional group (never shared). + */ +class DCMTK_DCMFG_EXPORT FGCTImageFrameType : public FGBase +{ +public: + static const OFString DT_VolBasedCalcTechnique_MaxIp; + static const OFString DT_VolBasedCalcTechnique_MinIp; + static const OFString DT_VolBasedCalcTechnique_VolumeRender; + static const OFString DT_VolBasedCalcTechnique_SurfaceRender; + static const OFString DT_VolBasedCalcTechnique_Mpr; + static const OFString DT_VolBasedCalcTechnique_CurvedMpr; + static const OFString DT_VolBasedCalcTechnique_None; + static const OFString DT_VolBasedCalcTechnique_Mixed; + + enum E_PixelPresentation + { + E_PixelPres_Color, + E_PixelPres_Monochrome, + E_PixelPres_Mixed, + E_PixelPres_TrueColor, + E_PixelPres_Empty, + E_PixelPres_Invalid + }; + + enum E_VolumetricProperties + { + E_VolProp_Volume, + E_VolProp_Sampled, + E_VolProp_Distorted, + E_VolProp_Mixed, + E_VolProp_Empty, + E_VolProp_Invalid + }; + + /** Constructor, creates empty functional group + */ + FGCTImageFrameType(); + + /** Virtual destructor + */ + virtual ~FGCTImageFrameType(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type (always "per-frame") + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Image Frame Type Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Image Frame Type Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Frame Type + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameType(OFString& value, const signed long pos = 0); + + /** Get Pixel Presentation + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getPixelPresentation(OFString& value, const signed long pos = 0); + + /** Get Pixel Presentation + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getPixelPresentation(E_PixelPresentation& value, const signed long pos = 0); + + /** Get Volumetric Properties + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getVolumetricProperties(OFString& value, const signed long pos = 0); + + /** Get Volumetric Properties + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getVolumetricProperties(E_VolumetricProperties& value, const signed long pos = 0); + + /** Get Volume Based Calculation Technique + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getVolumeBasedCalculationTechnique(OFString& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Frame Type + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Pixel Presentation + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setPixelPresentation(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Pixel Presentation + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setPixelPresentation(const E_PixelPresentation& value, const OFBool checkValue = OFTrue); + + /** Set Volumetric Properties + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setVolumetricProperties(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Volumetric Properties + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setVolumetricProperties(const E_VolumetricProperties& value, const OFBool checkValue = OFTrue); + + /** Set Volume Based Calculation Technique + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setVolumeBasedCalculationTechnique(const OFString& value, const OFBool checkValue = OFTrue); + + static E_PixelPresentation pixelPres2Enum(const OFString& str); + + static OFBool pixelPres2Str(const E_PixelPresentation& eval, OFString& result); + + static E_VolumetricProperties volProps2Enum(const OFString& str); + + static OFBool volProps2Str(const E_VolumetricProperties& eval, OFString& result); + +private: + /* Content of CT Image Frame Type Macro */ + + /// Frame Type (CS, VM 4, Required type 1) + DcmCodeString m_FrameType; + + /// Pixel Presentation (CS, 1, 1) + DcmCodeString m_PixelPresentation; + + /// Volumetric Properties (CS, 1, 1) + DcmCodeString m_VolumetricProperties; + + /// Volume Based Calculation Technique (CS, 1, 1) + DcmCodeString m_VolumeBasedCalculationTechnique; +}; + +#endif // FGCTIMAGEFRAMETYPE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctposition.h b/dcmfg/include/dcmtk/dcmfg/fgctposition.h new file mode 100644 index 00000000..40d1b0fa --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctposition.h @@ -0,0 +1,190 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Position Functional Group + * + */ + +#ifndef FGCTPOSITION_H +#define FGCTPOSITION_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Position" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTPosition : public FGBase +{ +public: + /** Constructor, creates empty functional group + */ + FGCTPosition(); + + /** Virtual destructor + */ + virtual ~FGCTPosition(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Position Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Position Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Table Speed + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTablePosition(OFString& value, const signed long pos = 0); + + /** Get Table Speed + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTablePosition(Float64& value, const unsigned long pos = 0); + + /** Get Data Collection Center (Patient) + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDataCollectionCenterPatient(OFString& value, const signed long pos = 0); + + /** Get Data Collection Center (Patient) + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDataCollectionCenterPatient(OFVector& values); + + /** Get Reconstruction Target Center (Patient) + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionTargetCenterPatient(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Target Center (Patient) + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionTargetCenterPatient(OFVector& values); + + // --- set() functionality --- + + /** Set Table Position + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTablePosition(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Data Collection Center (Patient) + * @param values Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setDataCollectionCenterPatient(const OFVector& values, + const OFBool checkValue = OFTrue); + + /** Set Reconstruction Target Center (Patient) + * @param values Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReconstructionTargetCenterPatient(const OFVector& values, + const OFBool checkValue = OFTrue); + +private: + /* Content of CT Position Macro */ + + /// Table Position (FD, VM 1, Required type 1C) + DcmFloatingPointDouble m_TablePosition; + + /// Data Collection Center (Patient) (FD, 3, 1C) + DcmFloatingPointDouble m_DataCollectionCenterPatient; + + /// Reconstruction Target Center (Patient) (FD, 3, 1C) + DcmFloatingPointDouble m_ReconstructionTargetCenterPatient; +}; + +#endif // FGCTPOSITION_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h b/dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h new file mode 100644 index 00000000..dff6d93c --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h @@ -0,0 +1,286 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Reconstruction Functional Group + * + */ + +#ifndef FGCTRECONSTRUCTION_H +#define FGCTRECONSTRUCTION_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Reconstruction" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTReconstruction : public FGBase +{ +public: + /** Constructor, creates empty functional group + */ + FGCTReconstruction(); + + /** Virtual destructor + */ + virtual ~FGCTReconstruction(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Reconstruction Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Reconstruction Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Reconstruction Algorithm + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionAlgorithm(OFString& value, const signed long pos = 0); + + /** Get Convolution Kernel + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getConvolutionKernel(OFString& value, const signed long pos = 0); + + /** Get Convolution Kernel Group + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getConvolutionKernelGroup(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Diameter + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionDiameter(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Diameter + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionDiameter(Float64& value, const unsigned long pos = 0); + + /** Get Reconstruction Field of View + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionFieldOfView(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Field of View + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionFieldOfView(OFVector& values); + + /** Get Reconstruction Pixel Spacing + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionPixelSpacing(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Pixel Spacing + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionPixelSpacing(OFVector& values); + + /** Get Reconstruction Angle + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionAngle(OFString& value, const signed long pos = 0); + + /** Get Reconstruction Angle + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReconstructionAngle(Float64& value, const unsigned long pos = 0); + + /** Get Image Filter + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getImageFilter(OFString& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Reconstruction Algorithm + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReconstructionAlgorithm(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Convolution Kernel + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setConvolutionKernel(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Convolution Kernel Group + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setConvolutionKernelGroup(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Reconstruction Diameter + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReconstructionDiameter(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Reconstruction Field of View + * @param value1 First value that should be set + * @param value2 Second value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition + setReconstructionFieldOfView(const Float64 value1, const Float64 value2, const OFBool checkValue = OFTrue); + + /** Set Reconstruction Pixel Spacing + * @param value1 First value that should be set + * @param value2 Second value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition + setReconstructionPixelSpacing(const Float64 value1, const Float64 value2, const OFBool checkValue = OFTrue); + /** Set Reconstruction Angle + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReconstructionAngle(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Image Filter + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setImageFilter(const OFString& value, const OFBool checkValue = OFTrue); + +private: + /* Content of CT Reconstruction Macro */ + + /// Reconstruction Algorithm (CS, VM 1, Required type 1C) + DcmCodeString m_ReconstructionAlgorithm; + + /// Convolution Kernel (SH, 1-n, 1C) + DcmShortString m_ConvolutionKernel; + + /// Convolution Kernel Group (CS, 1, 1C) + DcmCodeString m_ConvolutionKernelGroup; + + /// Reconstruction Diameter (DS, 1, 1C) + DcmDecimalString m_ReconstructionDiameter; + + /// Reconstruction Field of View (FD, 2, 1C) + DcmFloatingPointDouble m_ReconstructionFieldOfView; + + /// Reconstruction Pixel Spacing (FD, 2, 1C) + DcmFloatingPointDouble m_ReconstructionPixelSpacing; + + /// Reconstruction Angle (FD, 1, 1C) + DcmFloatingPointDouble m_ReconstructionAngle; + + /// Image Filter (SH, 1, 1C) + DcmShortString m_ImageFilter; +}; + +#endif // FGCTRECONSTRUCTION_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h b/dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h new file mode 100644 index 00000000..2cc6caf2 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h @@ -0,0 +1,267 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Table Dynamics Functional Group + * + */ + +#ifndef FGCTTABLEDYNAMICS_H +#define FGCTTABLEDYNAMICS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT Table Dynamics" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTTableDynamics : public FGBase +{ + +public: + /** Class representing an item of the "CT Table Dynamics" Functional Group Macro. + */ + class DCMTK_DCMFG_EXPORT FGCTTableDynamicsItem + { + + public: + /** Constructor, creates empty functional group item + */ + FGCTTableDynamicsItem(); + + /** Virtual destructor + */ + virtual ~FGCTTableDynamicsItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTTableDynamicsItem* clone() const; + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group item is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Table Dynamics Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTTableDynamicsItem& rhs) const; + + // --- get() functionality --- + + /** Get Table Speed + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTableSpeed(OFString& value, const signed long pos = 0); + + /** Get Tube Angle + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTableSpeed(Float64& value, const unsigned long pos = 0); + + /** Get Table Feed per Rotation + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTableFeedPerRotation(OFString& value, const signed long pos = 0); + + /** Get Table Feed per Rotation + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTableFeedPerRotation(Float64& value, const unsigned long pos = 0); + + /** Get Spiral Pitch Factor + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getSpiralPitchFactor(OFString& value, const signed long pos = 0); + + /** Get Spiral Pitch Factor + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getSpiralPitchFactor(Float64& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Table Speed + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTableSpeed(const Float64& value, const OFBool checkValue = OFTrue); + + /** Set Table Feed per Rotation + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTableFeedPerRotation(const Float64& value, const OFBool checkValue = OFTrue); + + /** Set Spiral Pitch Factor + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setSpiralPitchFactor(const Float64& value, const OFBool checkValue = OFTrue); + + private: + /* Content of CT Table Dynamics Macro (items) */ + + /// Acquisition Type (FD, VM 1, Required type 1C) + DcmFloatingPointDouble m_TableSpeed; + + /// Table Feed Rotation (FD, 1, 1C) + DcmFloatingPointDouble m_TableFeedPerRotation; + + /// Spiral Pitch Factor (FD, 1, 1C) + DcmFloatingPointDouble m_SpiralPitchFactor; + }; + + /** Constructor, creates empty functional group + */ + FGCTTableDynamics(); + + /** Virtual destructor + */ + virtual ~FGCTTableDynamics(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT Table Dynamics Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT Table Dynamics Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + OFVector& getCTTableDynamicsItems(); + +private: + /// Items of this functional group macro + OFVector m_Items; +}; + +#endif // FGCTTABLEDYNAMICS_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h b/dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h new file mode 100644 index 00000000..557fb2ef --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h @@ -0,0 +1,373 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT X-Ray Details Functional Group + * + */ + +#ifndef FGCTXRAYDETAILS_H +#define FGCTXRAYDETAILS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "CT X-Ray Details" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGCTXRayDetails : public FGBase +{ +public: + /** Constructor, creates empty functional group + */ + FGCTXRayDetails(); + + /** Virtual destructor + */ + virtual ~FGCTXRayDetails(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type + * @return The functional group type (DcmFGTypes::EFGS_BOTH) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT X-Ray Details Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT X-Ray Details Sequence + * (newly created) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Class representing the "CT X-Ray Details" Functional Group Macro. + */ + class DCMTK_DCMFG_EXPORT FGCTXRayDetailsItem + { + public: + /** Constructor, creates empty functional group + */ + FGCTXRayDetailsItem(); + + /** Virtual destructor + */ + virtual ~FGCTXRayDetailsItem(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGCTXRayDetailsItem* clone() const; + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read CT X-Ray Details Sequence item from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into CT X-Ray Details Sequence item + * given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGCTXRayDetailsItem& rhs) const; + + // --- get() functionality --- + + /** Get Referenced Path Index + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFString& value, const signed long pos = 0); + + /** Get Referenced Path Index + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getReferencedPathIndex(OFVector& values); + + /** Get KVP + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getKVP(OFString& value, const signed long pos = 0); + + /** Get KVP + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getKVP(Float64& value, const unsigned long pos = 0); + + /** Get Focal Spots + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFocalSpots(OFString& value, const signed long pos = 0); + + /** Get Focal Spots + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFocalSpots(OFVector& values); + + /** Get Filter Type + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFilterType(OFString& value, const signed long pos = 0); + + /** Get Filter Material + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFilterMaterial(OFString& value, const signed long pos = 0); + + /** Get Calcium Scoring Mass Factor Patient + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCalciumScoringMassFactorPatient(OFString& value, const signed long pos = 0); + + /** Get Calcium Scoring Mass Factor Patient + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCalciumScoringMassFactorPatient(Float32& value, const unsigned long pos = 0); + + /** Get Calcium Scoring Mass Factor Device + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCalciumScoringMassFactorDevice(OFString& value, const signed long pos = 0); + + /** Get Calcium Scoring Mass Factor Device + * @param values Reference to variable that should hold the result + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCalciumScoringMassFactorDevice(OFVector& values); + + /** Get Energy Weighting Factor + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getEnergyWeightingFactor(OFString& value, const signed long pos = 0); + + /** Get Energy Weighting Factor + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getEnergyWeightingFactor(Float32& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Referenced Path Index + * @param values Values that should be set + * @param checkValues If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setReferencedPathIndex(const OFVector& values, const OFBool checkValues = OFTrue); + + /** Set KVP + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setKVP(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Focal Spots + * @param values Values that should be set + * @param checkValues If OFTrue, basic checks are performed whether the values are + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFocalSpots(const OFVector& values, const OFBool checkValues = OFTrue); + + /** Set Filter Type + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFilterType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Filter Material + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFilterMaterial(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Calcium Scoring Mass Factor Patient + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setCalciumScoringMassFactorPatient(const Float32 value, const OFBool checkValue = OFTrue); + + /** Set Calcium Scoring Mass Factor Device + * @param values Values that should be set + * @param checkValues If OFTrue, basic checks are performed whether the values are + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setCalciumScoringMassFactorDevice(const OFVector& values, + const OFBool checkValues = OFTrue); + + /** Set Energy Weighting Factor + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setEnergyWeightingFactor(const Float32 value, const OFBool checkValue = OFTrue); + + private: + /* Content of CT X-Ray Details Macro */ + + /// Referenced Path Index (US, VM 1-n, Required type 1C) + DcmUnsignedShort m_ReferencedPathIndex; + + /// KVP (DS, 1, 1C) + DcmDecimalString m_KVP; + + /// Focal Spots (FD, 1-n, 1C) + DcmDecimalString m_FocalSpots; + + /// Filter Type (SH, 1, 1C) + DcmShortString m_FilterType; + + /// Filter Material (CS, 1-n, 1C) + DcmCodeString m_FilterMaterial; + + /// Calcium Scoring Mass Factor Patient (FL, 1, 3) + DcmFloatingPointSingle m_CalciumScoringMassFactorPatient; + + /// Calcium Scoring Mass Factor Device (FL, 3, 3) + DcmFloatingPointSingle m_CalciumScoringMassFactorDevice; + + /// Energy Weighting Factor (FD, 1, 1C) + DcmFloatingPointSingle m_EnergyWeightingFactor; + }; + + // --- get() functionality --- + + OFVector& getCTXRayDetailsItems(); + +private: + /* Content of CT X-Ray Details Macro item */ + + /// Items of CT X-Ray Details macro + OFVector m_Items; +}; + +#endif // FGCTXRAYDETAILS_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgdefine.h b/dcmfg/include/dcmtk/dcmfg/fgdefine.h index 72e2371a..896dd70a 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgdefine.h +++ b/dcmfg/include/dcmtk/dcmfg/fgdefine.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,13 +19,12 @@ * */ - #ifndef FGDEFINE_H #define FGDEFINE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofdefine.h" +#include "dcmtk/ofstd/ofdefine.h" #ifdef dcmfg_EXPORTS #define DCMTK_DCMFG_EXPORT DCMTK_DECL_EXPORT diff --git a/dcmfg/include/dcmtk/dcmfg/fgderimg.h b/dcmfg/include/dcmtk/dcmfg/fgderimg.h index 24b312eb..6a3b7986 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgderimg.h +++ b/dcmfg/include/dcmtk/dcmfg/fgderimg.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,15 +19,15 @@ * */ - #ifndef FGDERIMG_H #define FGDERIMG_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/ofstd/ofstring.h" -#include "dcmtk/dcmiod/iodmacro.h" + #include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing a single item of the Source Image Sequence */ @@ -35,269 +35,261 @@ class DCMTK_DCMFG_EXPORT SourceImageItem { public: - - /** Constructor, constructs empty Source Image Sequence item - */ - SourceImageItem(); - - /** Virtual destructor, cleans up memory - */ - virtual ~SourceImageItem(); - - /** Clears all data handled by this component - */ - virtual void clearData(); - - /** Check whether this item contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Return handle to to purpose of reference code - * @return EC_Normal if data is valid, error otherwise - */ - virtual CodeSequenceMacro& getPurposeOfReferenceCode(); - - /** Returns handle to to image sop instance reference - * @return EC_Normal if data is valid, error otherwise - */ - virtual ImageSOPInstanceReferenceMacro& getImageSOPInstanceReference(); - - /** Reads source image item from given item - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& itemOfSourceImageSequence, - const OFBool clearOldData = OFTrue); - - /** Writes source image item to given item - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& itemOfSourceImageSequence); - - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const SourceImageItem& rhs) const; - - /** Assignment operator, deletes old data - * @param rhs The item that should be assigned to "this" class - * @return Reference to "this" class - */ - SourceImageItem& operator=(const SourceImageItem& rhs); + /** Constructor, constructs empty Source Image Sequence item + */ + SourceImageItem(); + + /** Virtual destructor, cleans up memory + */ + virtual ~SourceImageItem(); + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Check whether this item contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Return handle to to purpose of reference code + * @return EC_Normal if data is valid, error otherwise + */ + virtual CodeSequenceMacro& getPurposeOfReferenceCode(); + + /** Returns handle to to image sop instance reference + * @return EC_Normal if data is valid, error otherwise + */ + virtual ImageSOPInstanceReferenceMacro& getImageSOPInstanceReference(); + + /** Reads source image item from given item + * @param itemOfSourceImageSequence Reference to item of Source Image Sequence + * @param clearOldData If OFTue, old data in this class is cleared before reading + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& itemOfSourceImageSequence, const OFBool clearOldData = OFTrue); + + /** Writes source image item to given item + * @param itemOfSourceImageSequence The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& itemOfSourceImageSequence); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const SourceImageItem& rhs) const; + + /** Assignment operator, deletes old data + * @param rhs The item that should be assigned to "this" class + * @return Reference to "this" class + */ + SourceImageItem& operator=(const SourceImageItem& rhs); private: + /// Describes purpose of reference (single item of Purpose of Reference Code + /// Sequence) + CodeSequenceMacro m_PurposeOfReferenceCode; - /// Describes purpose of reference (single item of Purpose of Reference Code - /// Sequence) - CodeSequenceMacro m_PurposeOfReferenceCode; - - /// Contains the referenced images (as represented by one of the items of - /// "this" Source Image Sequence) - ImageSOPInstanceReferenceMacro m_ImageSOPInstanceReference; + /// Contains the referenced images (as represented by one of the items of + /// "this" Source Image Sequence) + ImageSOPInstanceReferenceMacro m_ImageSOPInstanceReference; }; /// Iterator for traversing over items of the Source Image Sequence typedef OFVector::iterator SourceImageIterator; - /** Class representing a single item in Derivation Image Sequence */ class DCMTK_DCMFG_EXPORT DerivationImageItem { public: - - /** Constructor, initializes empty derivation image item - */ - DerivationImageItem(); - - /** Virtual destructor - */ - virtual ~DerivationImageItem(); - - /** Assignment operator, deletes old data - * @param rhs The item that should be assigned to "this" class - * @return Reference to "this" class - */ - DerivationImageItem& operator=(const DerivationImageItem& rhs); - - /** Copy constructor, deletes old data - * @param rhs The item that should be used for initialization - */ - DerivationImageItem(const DerivationImageItem& rhs); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type - * @param rhs The right hand side of the comparison - * @return 0 If the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. Also returned if rhs cannot be - * casted to DcmAttributeTag. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const DerivationImageItem& rhs) const; - - /** Clears all data handled by this component - */ - virtual void clearData(); - - /** Check whether item contains valid data - * @return EC_Normal if item is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Convenience function to add item representing reference to an object. No - * restrictions are set which frames or segments from this image has been - * actually used. However, such information could be added to the source - * image item later by modifying the resulting item being handed back to the - * caller. - * @param file Files that should be referenced by their UID, must be readable. - * @param purposeOfReference Code representing the purpose of reference - * (Defined CID 7202) - * @param resultSourceImageItem The created derivation image item if - * successful, NULL otherwise - * @return EC_Normal if adding works, error code otherwise - */ - virtual OFCondition addSourceImageItem(const OFString& file, - const CodeSequenceMacro& purposeOfReference, - SourceImageItem*& resultSourceImageItem); - - /** Convenience function to add item representing reference to an object. No - * restrictions are set which frames or segments from this image has been - * actually used. However, such information could be added to the source - * image item later by modifying the resulting item being handed back to the - * caller. - * @param dataset DICOM dataset that should be referenced by their UID - * @param purposeOfReference Code representing the purpose of reference - * (Defined CID 7202) - * @param resultSourceImageItem The created derivation image item if - * successful, NULL otherwise - * @return EC_Normal if adding works, error code otherwise - */ - virtual OFCondition addSourceImageItem(DcmDataset *dataset, - const CodeSequenceMacro& purposeOfReference, - SourceImageItem*& resultSourceImageItem); - - /** Convenience function to add items representing references to some objects - * which all have the same purpose of reference (code). No restrictions are - * set which frames or segments from those images have been actually used. - * However, such information could be added to the source image item later by - * modifying the resulting item handed back to the caller. - * @param files List of files that should be referenced by their UIDs. - * @param purposeOfReference Code representing the purpose of reference - * (Defined CID 7202) - * @param resultSourceImageItems The created derivation image items (one per - * file) if successful, NULL otherwise - * @param skipFileErrors If OFTrue, then files that could not be added will - * not lead to error. - * @return EC_Normal if adding works, error code otherwise - */ - virtual OFCondition addSourceImageItems(const OFVector& files, - const CodeSequenceMacro& purposeOfReference, - OFVector& resultSourceImageItems, - const OFBool skipFileErrors = OFFalse); - - /** Convenience function to add items representing references to some objects - * which all have the same purpose of reference (code). No restrictions are - * set which frames or segments from those images have been actually used. - * However, such information could be added to the source image item later by - * modifying the resulting item handed back to the caller. - * @param datasets List of datasets that should be referenced by their UIDs. - * @param purposeOfReference Code representing the purpose of reference - * (Defined CID 7202) - * @param resultSourceImageItems The created derivation image items (one per - * file) if successful, NULL otherwise - * @param skipErrors If OFTrue, then files that could not be added will - * not lead to error. - * @return EC_Normal if adding works, error code otherwise - */ - virtual OFCondition addSourceImageItems(const OFVector& datasets, - const CodeSequenceMacro& purposeOfReference, - OFVector& resultSourceImageItems, - const OFBool skipErrors = OFFalse); - - /** Get Derivation Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDerivationDescription(OFString &value, - const signed long pos = 0) const; - - /** Get reference to derivation code items - * @return Reference to derivation code items - */ - virtual OFVector& getDerivationCodeItems(); - - /** Get reference to source image items - * @return Reference to source image items - */ - virtual OFVector& getSourceImageItems(); - - /** Set Derivation Description - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDerivationDescription(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Read Derivation Image Sequence Item describing derivation from a - * set of images - * @param itemOfDerivationImageSequence The item to read from - * @param clearOldData If OFTrue, old data is deleted first - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& itemOfDerivationImageSequence, - const OFBool clearOldData = OFTrue); - - /** Write Derivation Image Sequence Item describing derivation from a - * set of images - * @param itemOfDerivationImageSequence The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& itemOfDerivationImageSequence); + /** Constructor, initializes empty derivation image item + */ + DerivationImageItem(); + + /** Virtual destructor + */ + virtual ~DerivationImageItem(); + + /** Assignment operator, deletes old data + * @param rhs The item that should be assigned to "this" class + * @return Reference to "this" class + */ + DerivationImageItem& operator=(const DerivationImageItem& rhs); + + /** Copy constructor, deletes old data + * @param rhs The item that should be used for initialization + */ + DerivationImageItem(const DerivationImageItem& rhs); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type + * @param rhs The right hand side of the comparison + * @return 0 If the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if rhs cannot be + * casted to DcmAttributeTag. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const DerivationImageItem& rhs) const; + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Check whether item contains valid data + * @return EC_Normal if item is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Convenience function to add item representing reference to an object. No + * restrictions are set which frames or segments from this image has been + * actually used. However, such information could be added to the source + * image item later by modifying the resulting item being handed back to the + * caller. + * @param file Files that should be referenced by their UID, must be readable. + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItem The created derivation image item if + * successful, NULL otherwise + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItem(const OFString& file, + const CodeSequenceMacro& purposeOfReference, + SourceImageItem*& resultSourceImageItem); + + /** Convenience function to add item representing reference to an object. No + * restrictions are set which frames or segments from this image has been + * actually used. However, such information could be added to the source + * image item later by modifying the resulting item being handed back to the + * caller. + * @param dataset DICOM dataset that should be referenced by their UID + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItem The created derivation image item if + * successful, NULL otherwise + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItem(DcmDataset* dataset, + const CodeSequenceMacro& purposeOfReference, + SourceImageItem*& resultSourceImageItem); + + /** Convenience function to add items representing references to some objects + * which all have the same purpose of reference (code). No restrictions are + * set which frames or segments from those images have been actually used. + * However, such information could be added to the source image item later by + * modifying the resulting item handed back to the caller. + * @param files List of files that should be referenced by their UIDs. + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItems The created derivation image items (one per + * file) if successful, NULL otherwise + * @param skipFileErrors If OFTrue, then files that could not be added will + * not lead to error. + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItems(const OFVector& files, + const CodeSequenceMacro& purposeOfReference, + OFVector& resultSourceImageItems, + const OFBool skipFileErrors = OFFalse); + + /** Convenience function to add items representing references to some objects + * which all have the same purpose of reference (code). No restrictions are + * set which frames or segments from those images have been actually used. + * However, such information could be added to the source image item later by + * modifying the resulting item handed back to the caller. + * @param datasets List of datasets that should be referenced by their UIDs. + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItems The created derivation image items (one per + * file) if successful, NULL otherwise + * @param skipErrors If OFTrue, then files that could not be added will + * not lead to error. + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItems(const OFVector& datasets, + const CodeSequenceMacro& purposeOfReference, + OFVector& resultSourceImageItems, + const OFBool skipErrors = OFFalse); + + /** Get Derivation Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDerivationDescription(OFString& value, const signed long pos = 0) const; + + /** Get reference to derivation code items + * @return Reference to derivation code items + */ + virtual OFVector& getDerivationCodeItems(); + + /** Get reference to source image items + * @return Reference to source image items + */ + virtual OFVector& getSourceImageItems(); + + /** Set Derivation Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDerivationDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Read Derivation Image Sequence Item describing derivation from a + * set of images + * @param itemOfDerivationImageSequence The item to read from + * @param clearOldData If OFTrue, old data is deleted first + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& itemOfDerivationImageSequence, const OFBool clearOldData = OFTrue); + + /** Write Derivation Image Sequence Item describing derivation from a + * set of images + * @param itemOfDerivationImageSequence The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& itemOfDerivationImageSequence); private: + // DICOM attributes. + // The comments for each attribute describe "Name: (VR, VM, Type)". + // See DICOM standard for further reference. - // DICOM attributes. - // The comments for each attribute describe "Name: (VR, VM, Type)". - // See DICOM standard for further reference. - - /// Derivation Description: (ST, 1, 3) - DcmShortText m_DerivationDescription; + /// Derivation Description: (ST, 1, 3) + DcmShortText m_DerivationDescription; - /// List of derivation codes for this set of images (1-n items permitted) - OFVector m_DerivationCodeItems; - - // List of source images, as described by Source Image Sequence (0-n items - // permitted) - OFVector m_SourceImageItems; + /// List of derivation codes for this set of images (1-n items permitted) + OFVector m_DerivationCodeItems; + // List of source images, as described by Source Image Sequence (0-n items + // permitted) + OFVector m_SourceImageItems; }; /** Class representing the "Derivation Image Functional Group Macro" @@ -305,110 +297,110 @@ private: class DCMTK_DCMFG_EXPORT FGDerivationImage : public FGBase { public: - - /** Constructor creating an empty functional group - */ - FGDerivationImage(); - - /** Virtual destructor, frees memory - */ - virtual ~FGDerivationImage(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Convenience function to create a minimalistic FGDerivationImage - * @param derivationImages The list of SOP instances to reference - * @param derivationDescription Description of the derivation performed - * @param derivationCode Coded representation of the derivation description - * @param purposeOfReference Purpose of referencing the SOP instances - * @return The created derivation image item, if successful, NULL otherwise - */ - static FGDerivationImage* createMinimal(const OFVector& derivationImages, - const OFString& derivationDescription, - const CodeSequenceMacro& derivationCode, - const CodeSequenceMacro& purposeOfReference); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGDerivationImage) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - /** Returns shared type of this functional group - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Convenience function to add an item only having a single derivation code - * derivation description. No source images have to provided but can be added - * later on the resulting DerivationImageItem. - * @param derivationCode Code describing derivation - * @param derivationDescription Free text description of derivation (can be - * empty) - * @param item The created derivation image item if successful, NULL - * otherwise - * @return EC_Normal if adding works, error code otherwise - */ - virtual OFCondition addDerivationImageItem(const CodeSequenceMacro& derivationCode, - const OFString& derivationDescription, - DerivationImageItem*& item); - - /** Clears all data handled by this component - */ - virtual void clearData(); - - /** Checks whether this class contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Get reference to derivation image items - * @return Reference to derivation image items - */ - virtual OFVector& getDerivationImageItems(); - - /** Read Derivation Image Sequence from given item, which can contain zero or - * more items - * @param item The item to read from - * @return Returns EC_Normal if at least one derivation image item could be - * read or no item exists at all, otherwise an error is returned - */ - virtual OFCondition read(DcmItem& item); - - /** Write Derivation Image Sequence (containing contain zero or more items) - * to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /** Constructor creating an empty functional group + */ + FGDerivationImage(); + + /** Virtual destructor, frees memory + */ + virtual ~FGDerivationImage(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Convenience function to create a minimalistic FGDerivationImage + * @param derivationImages The list of SOP instances to reference + * @param derivationDescription Description of the derivation performed + * @param derivationCode Coded representation of the derivation description + * @param purposeOfReference Purpose of referencing the SOP instances + * @return The created derivation image item, if successful, NULL otherwise + */ + static FGDerivationImage* createMinimal(const OFVector& derivationImages, + const OFString& derivationDescription, + const CodeSequenceMacro& derivationCode, + const CodeSequenceMacro& purposeOfReference); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGDerivationImage) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Returns shared type of this functional group + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Convenience function to add an item only having a single derivation code + * derivation description. No source images have to provided but can be added + * later on the resulting DerivationImageItem. + * @param derivationCode Code describing derivation + * @param derivationDescription Free text description of derivation (can be + * empty) + * @param item The created derivation image item if successful, NULL + * otherwise + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addDerivationImageItem(const CodeSequenceMacro& derivationCode, + const OFString& derivationDescription, + DerivationImageItem*& item); + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Checks whether this class contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Get reference to derivation image items + * @return Reference to derivation image items + */ + virtual OFVector& getDerivationImageItems(); + + /** Read Derivation Image Sequence from given item, which can contain zero or + * more items + * @param item The item to read from + * @return Returns EC_Normal if at least one derivation image item could be + * read or no item exists at all, otherwise an error is returned + */ + virtual OFCondition read(DcmItem& item); + + /** Write Derivation Image Sequence (containing contain zero or more items) + * to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); private: - - /// List of derivation image items making up the Derivation Image Sequence - OFVector m_DerivationImageItems; - + /// List of derivation image items making up the Derivation Image Sequence + OFVector m_DerivationImageItems; }; #endif // FGDERIMG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgfact.h b/dcmfg/include/dcmtk/dcmfg/fgfact.h index c44de470..72ce723f 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgfact.h +++ b/dcmfg/include/dcmtk/dcmfg/fgfact.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,58 +23,59 @@ #define FGFACT_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmap.h" + #include "dcmtk/dcmdata/dctagkey.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofmap.h" class FGBase; - /** Singleton class that is used to create functional groups by knowing * their type or other unique features, i.e.\ offering factory functionality. */ class DCMTK_DCMFG_EXPORT FGFactory { public: - - /** Return the single instance of the factory - * @return The instance of FGFactory - */ - static FGFactory& instance(); - - /** Create new functional group based on given type - * @param fgtype The type of functional group to create - * @return The functional group or NULL if error occurs - */ - FGBase *create(const DcmFGTypes::E_FGType fgtype); - - /** Create new functional group based its unique sequence tag key - * @param fgSequenceKey Tag key of the functional groups sequence - * @return The functional group or NULL if error occurs - */ - FGBase *create(const DcmTagKey& fgSequenceKey); + /** Return the single instance of the factory + * @return The instance of FGFactory + */ + static FGFactory& instance(); + + /** Create new functional group based on given type + * @param fgtype The type of functional group to create + * @return The functional group or NULL if error occurs + */ + FGBase* create(const DcmFGTypes::E_FGType fgtype); + + /** Create new functional group based its unique sequence tag key + * @param fgSequenceKey Tag key of the functional groups sequence + * @return The functional group or NULL if error occurs + */ + FGBase* create(const DcmTagKey& fgSequenceKey); private: - - /** Private undefined constructor (singleton implementation) - */ - FGFactory(); - - /** Private undefined copy constructor (singleton implementation) - */ - FGFactory(const FGFactory&); - - /** Private undefined assignment operator (singleton implementation) - */ - FGFactory& operator=(const FGFactory&); - - /** Private undefined destructor (singleton implementation) - */ - ~FGFactory() {} - - /// The instance of FGFactory handled by this singleton class - static FGFactory* m_Instance; - + /** Private undefined constructor (singleton implementation) + */ + FGFactory(); + + /** Private undefined copy constructor (singleton implementation) + */ + FGFactory(const FGFactory&); + + /** Private undefined assignment operator (singleton implementation) + * @param rhs Right hand side of assignment + * @return Reference to this class + */ + FGFactory& operator=(const FGFactory& rhs); + + /** Private undefined destructor (singleton implementation) + */ + ~FGFactory() + { + } + + /// The instance of FGFactory handled by this singleton class + static FGFactory* m_Instance; }; #endif // FGFACT_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgfracon.h b/dcmfg/include/dcmtk/dcmfg/fgfracon.h index 2aea9849..1cc3f688 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgfracon.h +++ b/dcmfg/include/dcmtk/dcmfg/fgfracon.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,10 +23,11 @@ #define FGFRACON_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/ofstd/ofstring.h" + #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the "Frame Content" Functional Group Macro. Can only be * used as per-frame functional group (never shared). @@ -34,345 +35,306 @@ class DCMTK_DCMFG_EXPORT FGFrameContent : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGFrameContent(); - - /** Virtual destructor - */ - virtual ~FGFrameContent(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Returns shared functional group type (always "per-frame") - * @return The functional group type (DcmFGTypes::EFGS_ONLYPERFRAME) - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_ONLYPERFRAME;} - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether the current content of this group is consistent and complete - * @return EC_Normal, if no errors are found, error otherwise - */ - virtual OFCondition check() const; - - /** Read Frame Content Sequence from given item - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Writes the content of this class into Frame Content Sequence - * (newly cerated) into given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - // --- get() functionality --- - - /** Get Frame Acquisition Number - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameAcquisitionNumber(Uint16& value, - const signed long pos = 0); - - /** Get Frame Reference Date Time - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameReferenceDateTime(OFString& value, - const signed long pos = 0); - /** Get Frame Acquisition Date Time - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameAcquisitionDateTime(OFString& value, - const signed long pos = 0); - - /** Get Frame Acquisition Duration - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameAcquisitionDuration(Float64& value, - const unsigned long pos = 0); - - /** Get Cardiac Cycle Position - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getCardiacCyclePosition(OFString& value, - const signed long pos = 0); - - /** Get Respiratory Cycle Position - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getRespiratoryCyclePosition(OFString& value, - const signed long pos = 0); - - /** Get Dimension Index Value - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getDimensionIndexValues(Uint32& value, - const signed long pos = 0); - - /** Get Temporal Position Index - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getTemporalPositionIndex(Uint32& value, - const signed long pos = 0); - - /** Get Stack ID - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getStackID(OFString& value, - const signed long pos = 0); - - /** Get In-Stack Position Number - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getInStackPositionNumber(Uint32& value, - const signed long pos = 0); - - /** Get Frame Comments - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameComments(OFString& value, - const signed long pos = 0); - - /** Get Frame Label - * @param value Reference to variable that should hold the result - * @param pos Position of the value inside the DICOM element. If 0, the first - * value is returned. If the no value at the given position exists, - * an error is returned. - * @return EC_Normal, if value could be returned, error otherwise - */ - virtual OFCondition getFrameLabel(OFString& value, - const signed long pos = 0); - - // --- set() functionality --- - - /** Set Frame Acquisition Number - * @param value Value that should be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameAcquisitionNumber(const Uint16& value, - const OFBool checkValue = OFTrue); - - /** Set Frame Frame Reference Date Time - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameReferenceDateTime(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Frame Acquisition Date Time - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameAcquisitionDateTime(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Frame Acquisition Duration - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameAcquisitionDuration(const Float64& value, - const OFBool checkValue = OFTrue); - - /** Set Cardiac Cycle Position - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setCardiacCyclePosition(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Respiratory Cycle Position - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setRespiratoryCyclePosition(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set one of the Dimension Index Values - * @param value Value that should be set (lowest index starts with 1) - * @param dim The position of the value that should be set (lowest index - * starts with 0), i.e.\ select the 1st, 2nd, ..nth dimension - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setDimensionIndexValues(const Uint32& value, - const unsigned int dim, - const OFBool checkValue = OFTrue); - - /** Set Temporal Position Index - * @param value Value that should be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setTemporalPositionIndex(const Uint32& value, - const OFBool checkValue = OFTrue); - - /** Set Stack ID - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setStackID(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set In-Stack Position Number - * @param value Value that should be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setInStackPositionNumber(const Uint32& value, - const OFBool checkValue = OFTrue); - - /** Set Frame Comments - * @param value Value that should be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameComments(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Frame Label - * @param value Value that should be set - * @param checkValue If OFTrue, basic checks are performed whether the value is - * valid for this attribute - * @return EC_Normal, if value was set, error otherwise - */ - virtual OFCondition setFrameLabel(const OFString& value, - const OFBool checkValue = OFTrue); + /** Constructor, creates empty functional group + */ + FGFrameContent(); + + /** Virtual destructor + */ + virtual ~FGFrameContent(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type (always "per-frame") + * @return The functional group type (DcmFGTypes::EFGS_ONLYPERFRAME) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_ONLYPERFRAME; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read Frame Content Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into Frame Content Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Frame Acquisition Number + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionNumber(Uint16& value, const unsigned long pos = 0); + + /** Get Frame Reference Date Time + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameReferenceDateTime(OFString& value, const signed long pos = 0); + /** Get Frame Acquisition Date Time + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionDateTime(OFString& value, const signed long pos = 0); + + /** Get Frame Acquisition Duration + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionDuration(Float64& value, const unsigned long pos = 0); + + /** Get Cardiac Cycle Position + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCardiacCyclePosition(OFString& value, const signed long pos = 0); + + /** Get Respiratory Cycle Position + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRespiratoryCyclePosition(OFString& value, const signed long pos = 0); + + /** Get Dimension Index Value + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDimensionIndexValues(Uint32& value, const unsigned long pos = 0); + + /** Get Temporal Position Index + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTemporalPositionIndex(Uint32& value, const unsigned long pos = 0); + + /** Get Stack ID + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getStackID(OFString& value, const signed long pos = 0); + + /** Get In-Stack Position Number + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getInStackPositionNumber(Uint32& value, const unsigned long pos = 0); + + /** Get Frame Comments + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameComments(OFString& value, const signed long pos = 0); + + /** Get Frame Label + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameLabel(OFString& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Frame Acquisition Number + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionNumber(const Uint16& value, const OFBool checkValue = OFTrue); + + /** Set Frame Frame Reference Date Time + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameReferenceDateTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Frame Acquisition Date Time + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionDateTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Frame Acquisition Duration + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionDuration(const Float64& value, const OFBool checkValue = OFTrue); + + /** Set Cardiac Cycle Position + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setCardiacCyclePosition(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Respiratory Cycle Position + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setRespiratoryCyclePosition(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set one of the Dimension Index Values + * @param value Value that should be set (lowest index starts with 1) + * @param dim The position of the value that should be set (lowest index + * starts with 0), i.e.\ select the 1st, 2nd, ..nth dimension + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition + setDimensionIndexValues(const Uint32& value, const unsigned int dim, const OFBool checkValue = OFTrue); + + /** Set Temporal Position Index + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTemporalPositionIndex(const Uint32& value, const OFBool checkValue = OFTrue); + + /** Set Stack ID + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setStackID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set In-Stack Position Number + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setInStackPositionNumber(const Uint32& value, const OFBool checkValue = OFTrue); + + /** Set Frame Comments + * @param value Value that should be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameComments(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Frame Label + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameLabel(const OFString& value, const OFBool checkValue = OFTrue); private: + /* Content of Frame Content Macro */ - /* Content of Frame Content Macro */ - - /// Frame Acquisition Number (US, VM 1, Required type 3) - DcmUnsignedShort m_FrameAcquisitonNumber; + /// Frame Acquisition Number (US, VM 1, Required type 3) + DcmUnsignedShort m_FrameAcquisitonNumber; - /// Frame Reference DateTime (DT, 1, 1C) - DcmDateTime m_FrameReferenceDateTime; + /// Frame Reference DateTime (DT, 1, 1C) + DcmDateTime m_FrameReferenceDateTime; - /// Frame Acquisition DateTime (DT, 1, 1C) - DcmDateTime m_FrameAcquisitionDateTime; + /// Frame Acquisition DateTime (DT, 1, 1C) + DcmDateTime m_FrameAcquisitionDateTime; - /// Frame Acquisition Duration (FD, 1, 1C) - DcmFloatingPointDouble m_FrameAcquisitionDuration; + /// Frame Acquisition Duration (FD, 1, 1C) + DcmFloatingPointDouble m_FrameAcquisitionDuration; - /// Cardiac Cycle Position (CS, 1, 3) - DcmCodeString m_CardiacCyclePosition; + /// Cardiac Cycle Position (CS, 1, 3) + DcmCodeString m_CardiacCyclePosition; - /// Respiratory Cycle Position (CS, 1, 3) - DcmCodeString m_RespiratoryCyclePosition; + /// Respiratory Cycle Position (CS, 1, 3) + DcmCodeString m_RespiratoryCyclePosition; - /// Dimension Index Values (UL, 1-n, 1C) - DcmUnsignedLong m_DimensionIndexValues; + /// Dimension Index Values (UL, 1-n, 1C) + DcmUnsignedLong m_DimensionIndexValues; - /// Temporal Position Index (UL, 1, 1C) - DcmUnsignedLong m_TemporalPositionIndex; + /// Temporal Position Index (UL, 1, 1C) + DcmUnsignedLong m_TemporalPositionIndex; - /// Stack ID (SH, 1, 1C) - DcmShortString m_StackID; + /// Stack ID (SH, 1, 1C) + DcmShortString m_StackID; - /// In-Stack Position Number (UL, 1, 1C) - DcmUnsignedLong m_InStackPositionNumber; + /// In-Stack Position Number (UL, 1, 1C) + DcmUnsignedLong m_InStackPositionNumber; - /// Frame Comments (LT, 1, 3) - DcmLongText m_FrameComments; + /// Frame Comments (LT, 1, 3) + DcmLongText m_FrameComments; - /// Frame Label (LO, 1, 3) - DcmLongString m_FrameLabel; + /// Frame Label (LO, 1, 3) + DcmLongString m_FrameLabel; }; #endif // FGFRACON_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h b/dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h index c29a78e9..c3af3c52 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h +++ b/dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,135 +23,137 @@ #define FGFRAMEANATOMY_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmiod/iodmacro.h" #include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmiod/iodmacro.h" /** Class representing the Frame Anatomy Functional Group Macro */ class DCMTK_DCMFG_EXPORT FGFrameAnatomy : public FGBase { public: - - /** Enumerated values for attribute "Laterality" - */ - enum LATERALITY - { - /// Undefined (e.g.\ value not set) - LATERALITY_UNDEFINED, - /// Invalid Laterality, e.g. when invalid value is read from file - LATERALITY_INVALID, - /// Right body part - LATERALITY_R, - /// Left body part - LATERALITY_L, - /// Unpaired body part - LATERALITY_UNPAIRED, - /// Both, left and right - LATERALITY_BOTH - }; - - /** Constructor, creates empty Frame Anatomy Functional Group - */ - FGFrameAnatomy(); - - /** Virtual destructor, frees memory - */ - virtual ~FGFrameAnatomy(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Returns shared type of this group (can be shared or per-frame) - * @return Always returns DcmFGTypes::EFGS_BOTH; - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether data in functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from given item - * @param item The item to read from, must contain Frame Anatomy Sequence - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to given item - * @param item The item to write Frame Anatomy Sequence to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Laterality - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise (i.e. if - * value is LATERALITY_INVALID). - */ - virtual OFCondition getLaterality(LATERALITY& value); - - /** Get anatomy information - * @return Reference to anatomic information - */ - virtual GeneralAnatomyMacro& getAnatomy(); - - // --- set() functionality --- - - /** Set Laterality - * @param value Value to be set - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLaterality(const LATERALITY& value); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - static LATERALITY str2Laterality(const OFString& lat); - - static OFString laterality2Str(const LATERALITY lat); - - static OFBool isLateralityValid(const LATERALITY lat); + /** Enumerated values for attribute "Laterality" + */ + enum LATERALITY + { + /// Undefined (e.g.\ value not set) + LATERALITY_UNDEFINED, + /// Invalid Laterality, e.g. when invalid value is read from file + LATERALITY_INVALID, + /// Right body part + LATERALITY_R, + /// Left body part + LATERALITY_L, + /// Unpaired body part + LATERALITY_UNPAIRED, + /// Both, left and right + LATERALITY_BOTH + }; + + /** Constructor, creates empty Frame Anatomy Functional Group + */ + FGFrameAnatomy(); + + /** Virtual destructor, frees memory + */ + virtual ~FGFrameAnatomy(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared type of this group (can be shared or per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH; + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data in functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item + * @param item The item to read from, must contain Frame Anatomy Sequence + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item + * @param item The item to write Frame Anatomy Sequence to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Laterality + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise (i.e. if + * value is LATERALITY_INVALID). + */ + virtual OFCondition getLaterality(LATERALITY& value); + + /** Get anatomy information + * @return Reference to anatomic information + */ + virtual GeneralAnatomyMacro& getAnatomy(); + + // --- set() functionality --- + + /** Set Laterality + * @param value Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLaterality(const LATERALITY& value); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + static LATERALITY str2Laterality(const OFString& lat); + + static OFString laterality2Str(const LATERALITY lat); + + static OFBool isLateralityValid(const LATERALITY lat); private: + /* Content of Frame Anatomy Macro */ - /* Content of Frame Anatomy Macro */ - - /// Frame Laterality (DS, VM 1, Required type 1) - LATERALITY m_FrameLaterality; + /// Frame Laterality (DS, VM 1, Required type 1) + LATERALITY m_FrameLaterality; - /// General Anatomy Mandatory Macro - GeneralAnatomyMacro m_Anatomy; + /// General Anatomy Mandatory Macro + GeneralAnatomyMacro m_Anatomy; }; #endif // FGFRAMEANATOMY_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h b/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h index 81cb6605..32e83796 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h +++ b/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGFRAMEVOILUT_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgbase.h" @@ -31,179 +32,179 @@ class DCMTK_DCMFG_EXPORT FGFrameVOILUT : public FGBase { public: - - /** Constructor creating empty functional group - */ - FGFrameVOILUT(); - - /** Virtual destructor - */ - virtual ~FGFrameVOILUT(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Get shared type of this kind functional group (can be both, per-frame or - * shared) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear old values - */ - virtual void clearData(); - - /** Check whether functional group contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read Frame VOI LUT Sequence from given item - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write Frame VOI LUT Sequence to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Window Center - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getWindowCenter(Float64& value, - const unsigned long pos = 0); - - /** Get Window Width - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getWindowWidth(Float64& value, - const unsigned long pos = 0); - - /** Get Window Center and Window Width Explanation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getWindowCenterAndWindowWidthExplanation(OFString& value, - const unsigned long pos = 0); - - /** Get tripe of information: Window Center, Window With, Window Center and - * Window Width Explanation - * @param windowCenter Reference to variable in which Window Center should - * be stored - * @param windowWidth Reference to variable in which Window Width should - * be stored - * @param explanation Reference to variable in which Window Center and - * Window Width Explanation should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCenterWidthExplanation(Float64& windowCenter, - Float64& windowWidth, - OFString& explanation); - - /** Get VOI LUT Function - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVOILUTFunction(OFString& value, - const unsigned long pos = 0); - - - // --- set() functionality --- - - /** Set Window Center - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setWindowCenter(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Window Width - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setWindowWidth(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Window Center and Window Width Explanation - * @param windowCenter Value for Window Center - * @param windowWidth Value for Window Width - * @param explanation Value for Window Center and Window Width Explanation - * should be stored - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setCenterWidthExplanation(const Float64& windowCenter, - const Float64& windowWidth, - const OFString& explanation = "", - const OFBool checkValue = OFTrue); - - /** Set VOI LUT Function - * @param value Value for VOI LUT Function - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVOILUTFunction(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /// Defined Term "BRAIN" for tag Window Center & Width Explanation (0028,1055) for CT objects + static const OFString DT_CT_WindowCenterWidthExplanation_Brain; + /// Defined Term "SOFT_TISSUE" for tag Window Center & Width Explanation (0028,1055) for CT objects + static const OFString DT_CT_WindowCenterWidthExplanation_SoftTissue; + /// Defined Term "LUNG" for tag Window Center & Width Explanation (0028,1055) for CT objects + static const OFString DT_CT_WindowCenterWidthExplanation_Lung; + /// Defined Term "BONE" for tag Window Center & Width Explanation (0028,1055) for CT objects + static const OFString DT_CT_WindowCenterWidthExplanation_Bone; + + /** Constructor creating empty functional group + */ + FGFrameVOILUT(); + + /** Virtual destructor + */ + virtual ~FGFrameVOILUT(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this kind functional group (can be both, per-frame or + * shared) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear old values + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read Frame VOI LUT Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write Frame VOI LUT Sequence to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Window Center + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowCenter(Float64& value, const unsigned long pos = 0); + + /** Get Window Width + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowWidth(Float64& value, const unsigned long pos = 0); + + /** Get Window Center and Window Width Explanation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowCenterAndWindowWidthExplanation(OFString& value, const unsigned long pos = 0); + + /** Get tripe of information: Window Center, Window With, Window Center and + * Window Width Explanation + * @param windowCenter Reference to variable in which Window Center should + * be stored + * @param windowWidth Reference to variable in which Window Width should + * be stored + * @param explanation Reference to variable in which Window Center and + * Window Width Explanation should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCenterWidthExplanation(Float64& windowCenter, Float64& windowWidth, OFString& explanation); + + /** Get VOI LUT Function + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVOILUTFunction(OFString& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Window Center + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setWindowCenter(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Window Width + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setWindowWidth(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Window Center and Window Width Explanation + * @param windowCenter Value for Window Center + * @param windowWidth Value for Window Width + * @param explanation Value for Window Center and Window Width Explanation + * should be stored + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setCenterWidthExplanation(const Float64& windowCenter, + const Float64& windowWidth, + const OFString& explanation = "", + const OFBool checkValue = OFTrue); + + /** Set VOI LUT Function + * @param value Value for VOI LUT Function + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVOILUTFunction(const OFString& value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Frame VOI LUT Macro */ - /* Content of Frame VOI LUT Macro */ - - /// Window Center (DS, VM 1-n, Required type 1) - DcmDecimalString m_WindowCenter; + /// Window Center (DS, VM 1-n, Required type 1) + DcmDecimalString m_WindowCenter; - /// Window Width (DS, VM 1-n, Required type 1) - DcmDecimalString m_WindowWidth; + /// Window Width (DS, VM 1-n, Required type 1) + DcmDecimalString m_WindowWidth; - /// Window Center & Window Width Explanation (LO, VM 1-n, Required type 3) - DcmLongString m_WindowCenterWindowWidthExplanation; + /// Window Center & Window Width Explanation (LO, VM 1-n, Required type 3) + DcmLongString m_WindowCenterWindowWidthExplanation; - /// VOI LUT Function (CS, VM 1, Requirement Type 3) - DcmCodeString m_VOILUTFunction; + /// VOI LUT Function (CS, VM 1, Requirement Type 3) + DcmCodeString m_VOILUTFunction; }; #endif // FGFRAMEVOILUT_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h b/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h index 1ba990f4..1cb94bf7 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h +++ b/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGIMAGEDATATYPE_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgbase.h" @@ -32,148 +33,143 @@ class DCMTK_DCMFG_EXPORT FGImageDataType : public FGBase { public: - - /** Constructor, creates empty Image Data Type functional group - */ - FGImageDataType(); - - /** Destructor, frees memory - */ - virtual ~FGImageDataType(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Get potential shared type of this group, always returns - * DcmFGTypes::EFGS_BOTH - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear data - */ - virtual void clearData(); - - /** Check whether current data of this functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read Image Data Type Sequence (this functional group) from given item - * @param item Item to read from - * @return EC_Normal if reading works, error otherwise - */ - virtual OFCondition read(DcmItem &item); - - /** Write Image Data Type Sequence (this functional group) to given item - * @param item Item to write to - * @return EC_Normal if writing works, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Data Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDataType(OFString& value, - const signed long pos = 0); - - /** Get Aliased Data Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAliasedDataType(OFString& value, - const signed long pos = 0); - - /** Get Zero Velocity Pixel Value - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getZeroVelocityPixelValue(Sint32& value, - const signed long pos = 0); - - // --- set() functionality --- - - /** Set Data Type - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDataType(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Aliased Data Type - * @param value Permitted values: "YES" or "NO". - * @param checkValue If enabled, the value is checked for conformance - * @return EC_Normal if value was set, error code otherwise - */ - virtual OFCondition setAliasedDataType(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of - * VR US, i.e.\ Pixel Representation = 0 - * @param value Value to be set - - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setZeroVelocityPixelValueUS(const Uint16 value); - - /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of - * VR SS, i.e.\ Pixel Representation = 1 - * @param value Value to be set - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setZeroVelocityPixelValueSS(const Sint16 value); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty Image Data Type functional group + */ + FGImageDataType(); + + /** Destructor, frees memory + */ + virtual ~FGImageDataType(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get potential shared type of this group, always returns + * DcmFGTypes::EFGS_BOTH + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear data + */ + virtual void clearData(); + + /** Check whether current data of this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read Image Data Type Sequence (this functional group) from given item + * @param item Item to read from + * @return EC_Normal if reading works, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write Image Data Type Sequence (this functional group) to given item + * @param item Item to write to + * @return EC_Normal if writing works, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Data Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDataType(OFString& value, const signed long pos = 0); + + /** Get Aliased Data Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAliasedDataType(OFString& value, const signed long pos = 0); + + /** Get Zero Velocity Pixel Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getZeroVelocityPixelValue(Sint32& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Data Type + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDataType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Aliased Data Type + * @param value Permitted values: "YES" or "NO". + * @param checkValue If enabled, the value is checked for conformance + * @return EC_Normal if value was set, error code otherwise + */ + virtual OFCondition setAliasedDataType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of + * VR US, i.e.\ Pixel Representation = 0 + * @param value Value to be set + + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setZeroVelocityPixelValueUS(const Uint16 value); + + /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of + * VR SS, i.e.\ Pixel Representation = 1 + * @param value Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setZeroVelocityPixelValueSS(const Sint16 value); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Image Data Type Macro */ - /* Content of Image Data Type Macro */ - - /// Data Type (CS, VM 1, Required type 1) - DcmCodeString m_DataType; - - /// Aliased Data Type (CS, VM 1, Required Type 1) - DcmCodeString m_AliasedDataType; + /// Data Type (CS, VM 1, Required type 1) + DcmCodeString m_DataType; - /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) - DcmUnsignedShort m_ZeroVelocityPixelValueUS; + /// Aliased Data Type (CS, VM 1, Required Type 1) + DcmCodeString m_AliasedDataType; - /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) - DcmSignedShort m_ZeroVelocityPixelValueSS; + /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) + DcmUnsignedShort m_ZeroVelocityPixelValueUS; + /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) + DcmSignedShort m_ZeroVelocityPixelValueSS; }; #endif // FGIMAGEDATATYPE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fginterface.h b/dcmfg/include/dcmtk/dcmfg/fginterface.h index bd9c6cc5..8570efea 100644 --- a/dcmfg/include/dcmtk/dcmfg/fginterface.h +++ b/dcmfg/include/dcmtk/dcmfg/fginterface.h @@ -23,15 +23,16 @@ #define FGINTERFACE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/ofstd/ofmap.h" -#include "dcmtk/dcmdata/dcsequen.h" + #include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dctk.h" -#include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmfg/fgtypes.h" -#include "dcmtk/dcmfg/fgdefine.h" #include "dcmtk/dcmfg/fg.h" +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofvector.h" // Forward declaration class IODMultiframeDimensionModule; @@ -44,274 +45,261 @@ class DCMTK_DCMFG_EXPORT FGInterface { public: - - /// Type representing per-frame functional groups, i.e.\ a number of - /// functional groups assigned to each frame - typedef OFMap PerFrameGroups; - - /// Iterator type for iterating over functional groups - typedef FunctionalGroups::iterator iterator; - - /// Const iterator type for iterating over functional groups - typedef FunctionalGroups::const_iterator const_iterator; - - /** Constructor, constructs empty sets of per-frame and shared - * functional groups - */ - FGInterface(); - - /** Virtual destructor, frees memory - */ - virtual ~FGInterface(); - - /** Delete all functional groups (shared and per-frame) - */ - virtual void clear(); - - /** Checks the functional groups for consistency. The following checks are - * performed: - * -# Check that every frame has a FrameContent functional group. - * -# Check that any per-frame group is not shared at the same time. - * -# Check for each per-frame group, that it is allowed to be per-frame. - * -# Check for each shared group, that it is allowed to be shared. - * @return OFTrue, if check consistency is ok, error otherwise - */ - virtual OFBool check(); - - /** Returns number of frames. Computed by number of per-frame - * functional group items (i.e.\ the Number of Frames attribute - * is not taken into account). - * @return Number of frames - */ - virtual size_t getNumberOfFrames(); - - /** Read enhanced multi-frame information from DICOM item, usually - * DcmDataset, i.e.\ must contain Shared and Per-frame Functional Group - * Sequences - * @param dataset The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& dataset); - - /** Write enhanced multi-frame information to DICOM item, - * usually DcmDataset, i.e.\ writes Shared and Per-frame Functional Group - * Sequences - * @param dataset The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& dataset); - - /** Get specific functional group for a frame, no matter whether it is stored - * per frame or shared - * @param frameNo The frame number the functional group should apply to - * (starts with 0) - * @param fgType The type of functional group to look for - * @return The functional group if found, NULL otherwise - */ - virtual FGBase* get(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType); - - // TODO Add get(..) version that takes the sequence tag (e.g.\ for unknown - // functional groups - - /** Get specific functional group for a frame, no matter whether it is stored - * per frame or shared. - * @param frameNo The frame number of group of interest (starts from 0) - * @param fgType The type of functional group to look for - * @param isPerFrame If OFTrue, the group found was found as per-frame, - * otherwise it is a shared functional group - * @return The functional group if found, error otherwise - */ - virtual FGBase* get(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType, - OFBool& isPerFrame); - - /** Return all per-frame functional groups, e.g.\ to iterate over them - * @param frameNo The frame number of the groups of interest (starts from 0) - * @return The per-frame functional groups for the given frame - */ - const FunctionalGroups* getPerFrame(const Uint32 frameNo) const; - - /** Return all shared functional groups, e.g.\ to iterate over them - * @return The shared functional groups - */ - const FunctionalGroups* getShared() const; - - /** Add functional group that should be shared for all frames. This will - * delete all per-frame groups of the same type if existing. - * @param group The group to be added. The group is copied. - * @return EC_Normal, if adding was successful, error otherwise - */ - virtual OFCondition addShared(const FGBase& group); - - /** Add functional group for given frame. If there is already a shared - * functional group with identical values, the call returns without - * errors, too. If there is a shared group that differs, the shared group - * is converted to be "per-frame" for all frames and then the given group - * is inserted for the frame specified by the user. - * If a per-frame functional group of the same type already exists it is - * overwritten. - * @param frameNo The frame number this group should be added for (starts - * from 0) - * @param group The group to be added. The group is copied when adding, - * so the ownership stays with the caller, no matter what the - * method returns. - * @return EC_Normal, if adding was successful, error otherwise - */ - virtual OFCondition addPerFrame(const Uint32 frameNo, - const FGBase& group); - - /** Deletes a shared functional group of the given type - * @param fgType The type of functional group to delete - * @return OFTrue if group existed and could be deleted, OFFalse (group did - * not exist) otherwise - */ - virtual OFBool deleteShared(const DcmFGTypes::E_FGType fgType); - - /** Deletes per-frame functional group of the given type for a specific frame - * @param frameNo The frame number for the functional group of interest. - * First frame is frame 0. - * @param fgType The type of functional group to delete - * @return OFTrue if group existed and could be deleted, OFFalse (group did - * not exist) otherwise - */ - virtual OFBool deletePerFrame(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType); - - /** Deletes per-frame functional group for all frames - * @param fgType The type of functional group to delete - * @return Number of per-frame groups deleted (usually equal to number of - * frames) - */ - size_t deletePerFrame(const DcmFGTypes::E_FGType fgType); - - /** Deletes all functional groups for a specific frame - * @param frameNo The frame number whose functional groups should be deleted. - * First frame is frame 0. - * @return Number of per-frame groups deleted for this frame - */ - size_t deleteFrame(const Uint32 frameNo); - - /** If enabled, functional group structure is checked before actual writing - * is performed in the write() method. Checking might be time consuming - * on functional groups with many frames, though disabling might result in - * invalid functional group structures. Disabling should only be done if the - * user knows that the functional groups are valid, wants to to adapt the - * functional groups manually after calling write() or knows what he's doing - * otherwise.
- * Per default, checking is enabled. - * @param doCheck If OFTrue, checking will be performed. If OFFalse, - * no checks are performed. - */ - virtual void setCheckOnWrite(const OFBool doCheck); - - /** Returns whether functional group structure is checked before actual - * writing is performed in the write() method. - * @return OFTrue if checking is performed, OFFalse otherwise - */ - virtual OFBool getCheckOnWrite(); + /// Type representing per-frame functional groups, i.e.\ a number of + /// functional groups assigned to each frame + typedef OFMap PerFrameGroups; + + /// Iterator type for iterating over functional groups + typedef FunctionalGroups::iterator iterator; + + /// Const iterator type for iterating over functional groups + typedef FunctionalGroups::const_iterator const_iterator; + + /** Constructor, constructs empty sets of per-frame and shared + * functional groups + */ + FGInterface(); + + /** Virtual destructor, frees memory + */ + virtual ~FGInterface(); + + /** Delete all functional groups (shared and per-frame) + */ + virtual void clear(); + + /** Checks the functional groups for consistency. The following checks are + * performed: + * -# Check that every frame has a FrameContent functional group. + * -# Check that any per-frame group is not shared at the same time. + * -# Check for each per-frame group, that it is allowed to be per-frame. + * -# Check for each shared group, that it is allowed to be shared. + * @return OFTrue, if check consistency is ok, error otherwise + */ + virtual OFBool check(); + + /** Returns number of frames. Computed by number of per-frame + * functional group items (i.e.\ the Number of Frames attribute + * is not taken into account). + * @return Number of frames + */ + virtual size_t getNumberOfFrames(); + + /** Read enhanced multi-frame information from DICOM item, usually + * DcmDataset, i.e.\ must contain Shared and Per-frame Functional Group + * Sequences + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& dataset); + + /** Write enhanced multi-frame information to DICOM item, + * usually DcmDataset, i.e.\ writes Shared and Per-frame Functional Group + * Sequences + * @param dataset The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& dataset); + + /** Get specific functional group for a frame, no matter whether it is stored + * per frame or shared + * @param frameNo The frame number the functional group should apply to + * (starts with 0) + * @param fgType The type of functional group to look for + * @return The functional group if found, NULL otherwise + */ + virtual FGBase* get(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType); + + // TODO Add get(..) version that takes the sequence tag (e.g.\ for unknown + // functional groups + + /** Get specific functional group for a frame, no matter whether it is stored + * per frame or shared. + * @param frameNo The frame number of group of interest (starts from 0) + * @param fgType The type of functional group to look for + * @param isPerFrame If OFTrue, the group found was found as per-frame, + * otherwise it is a shared functional group + * @return The functional group if found, error otherwise + */ + virtual FGBase* get(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType, OFBool& isPerFrame); + + /** Return all per-frame functional groups, e.g.\ to iterate over them + * @param frameNo The frame number of the groups of interest (starts from 0) + * @return The per-frame functional groups for the given frame + */ + const FunctionalGroups* getPerFrame(const Uint32 frameNo) const; + + /** Return all shared functional groups, e.g.\ to iterate over them + * @return The shared functional groups + */ + const FunctionalGroups* getShared() const; + + /** Add functional group that should be shared for all frames. This will + * delete all per-frame groups of the same type if existing. + * @param group The group to be added. The group is copied. + * @return EC_Normal, if adding was successful, error otherwise + */ + virtual OFCondition addShared(const FGBase& group); + + /** Add functional group for given frame. If there is already a shared + * functional group with identical values, the call returns without + * errors, too. If there is a shared group that differs, the shared group + * is converted to be "per-frame" for all frames and then the given group + * is inserted for the frame specified by the user. + * If a per-frame functional group of the same type already exists it is + * overwritten. + * @param frameNo The frame number this group should be added for (starts + * from 0) + * @param group The group to be added. The group is copied when adding, + * so the ownership stays with the caller, no matter what the + * method returns. + * @return EC_Normal, if adding was successful, error otherwise + */ + virtual OFCondition addPerFrame(const Uint32 frameNo, const FGBase& group); + + /** Deletes a shared functional group of the given type + * @param fgType The type of functional group to delete + * @return OFTrue if group existed and could be deleted, OFFalse (group did + * not exist) otherwise + */ + virtual OFBool deleteShared(const DcmFGTypes::E_FGType fgType); + + /** Deletes per-frame functional group of the given type for a specific frame + * @param frameNo The frame number for the functional group of interest. + * First frame is frame 0. + * @param fgType The type of functional group to delete + * @return OFTrue if group existed and could be deleted, OFFalse (group did + * not exist) otherwise + */ + virtual OFBool deletePerFrame(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType); + + /** Deletes per-frame functional group for all frames + * @param fgType The type of functional group to delete + * @return Number of per-frame groups deleted (usually equal to number of + * frames) + */ + size_t deletePerFrame(const DcmFGTypes::E_FGType fgType); + + /** Deletes all functional groups for a specific frame + * @param frameNo The frame number whose functional groups should be deleted. + * First frame is frame 0. + * @return Number of per-frame groups deleted for this frame + */ + size_t deleteFrame(const Uint32 frameNo); + + /** If enabled, functional group structure is checked before actual writing + * is performed in the write() method. Checking might be time consuming + * on functional groups with many frames, though disabling might result in + * invalid functional group structures. Disabling should only be done if the + * user knows that the functional groups are valid, wants to to adapt the + * functional groups manually after calling write() or knows what he's doing + * otherwise.
+ * Per default, checking is enabled. + * @param doCheck If OFTrue, checking will be performed. If OFFalse, + * no checks are performed. + */ + virtual void setCheckOnWrite(const OFBool doCheck); + + /** Returns whether functional group structure is checked before actual + * writing is performed in the write() method. + * @return OFTrue if checking is performed, OFFalse otherwise + */ + virtual OFBool getCheckOnWrite(); protected: - - /** Get shared functional group based on its type - * @param fgType The type of functional group - * @return The functional group or NULL if not existent - */ - virtual FGBase* getShared(const DcmFGTypes::E_FGType fgType); - - /** Insert shared functional group - * @param group The functional group to be inserted - * @param replaceExisting If OFTrue, an existing shared functional group - * will be deleted, otherwise the old group is not overwritten - * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and - * is not overwritten, other error code for other cases - */ - virtual OFCondition insertShared(FGBase* group, - const OFBool replaceExisting = OFTrue); - - /** Get per-frame functional group - * @param frameNo The frame number of the group - * @param fgType The type of the group - * @return The functional group or NULL if not existent - */ - virtual FGBase* getPerFrame(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType); - - /** Insert per-frame functional group - * @param frameNo The frame number the group should be added for - * @param group The functional group to be inserted - * @param replaceExisting If OFTrue, an existing per-frame functional group - * will be deleted, otherwise the old group is not overwritten - * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and - * is not overwritten, other error code for other cases - */ - virtual OFCondition insertPerFrame(const Uint32 frameNo, - FGBase* group, - const OFBool replaceExisting = OFTrue); - - /** Get existing per-frame group or create it for the given frame. Note that - * the per-frame groups do not have to be created "in order", i.e.\ one could - * add groups in order 3,5,1 ,... . - * @param frameNo The frame number to get/create per-frame groups for - * @return The functional groups if found/created, NULL in case of error - */ - virtual FunctionalGroups* getOrCreatePerFrameGroups(const Uint32 frameNo); - - /** Read Shared Functional Group Sequence from given item - * @param dataset The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readSharedFG(DcmItem& dataset); - - /** Read Per-Frame Functional Group Sequence from given item - * @param dataset The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readPerFrameFG(DcmItem& dataset); - - /** Read single functional group into the item provided - * @param fgItem The item to read from - * @param groups The resulting group after reading - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readSingleFG(DcmItem& fgItem, - FunctionalGroups& groups); - - /** Write Shared Functional Group Sequence to given item - * @param dataset The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeSharedFG(DcmItem& dataset); - - /** Write Per-Frame Functional Group Sequence to given item - * @param dataset The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writePerFrameFG(DcmItem& dataset); - - /** Convert a shared functional group to a per-frame one by copying the - * shared one into a per-frame one for each frame and deleting the shared one - * aftewrards. - * @param fgType The type of functional group to convert - * @return EC_Normal if conversion worked out, FG_EC_NoSuchGroup if such a - * group does not exist and other error otherwise. In the last case - * the functional groups may be left in invalid state, but that - * should only happen for fatal errors like exhausted memory. - */ - virtual OFCondition convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType); + /** Get shared functional group based on its type + * @param fgType The type of functional group + * @return The functional group or NULL if not existent + */ + virtual FGBase* getShared(const DcmFGTypes::E_FGType fgType); + + /** Insert shared functional group + * @param group The functional group to be inserted + * @param replaceExisting If OFTrue, an existing shared functional group + * will be deleted, otherwise the old group is not overwritten + * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and + * is not overwritten, other error code for other cases + */ + virtual OFCondition insertShared(FGBase* group, const OFBool replaceExisting = OFTrue); + + /** Get per-frame functional group + * @param frameNo The frame number of the group + * @param fgType The type of the group + * @return The functional group or NULL if not existent + */ + virtual FGBase* getPerFrame(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType); + + /** Insert per-frame functional group + * @param frameNo The frame number the group should be added for + * @param group The functional group to be inserted + * @param replaceExisting If OFTrue, an existing per-frame functional group + * will be deleted, otherwise the old group is not overwritten + * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and + * is not overwritten, other error code for other cases + */ + virtual OFCondition insertPerFrame(const Uint32 frameNo, FGBase* group, const OFBool replaceExisting = OFTrue); + + /** Get existing per-frame group or create it for the given frame. Note that + * the per-frame groups do not have to be created "in order", i.e.\ one could + * add groups in order 3,5,1 ,... . + * @param frameNo The frame number to get/create per-frame groups for + * @return The functional groups if found/created, NULL in case of error + */ + virtual FunctionalGroups* getOrCreatePerFrameGroups(const Uint32 frameNo); + + /** Read Shared Functional Group Sequence from given item + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSharedFG(DcmItem& dataset); + + /** Read Per-Frame Functional Group Sequence from given item + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readPerFrameFG(DcmItem& dataset); + + /** Read single functional group into the item provided + * @param fgItem The item to read from + * @param groups The resulting group after reading + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSingleFG(DcmItem& fgItem, FunctionalGroups& groups); + + /** Write Shared Functional Group Sequence to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeSharedFG(DcmItem& dataset); + + /** Write Per-Frame Functional Group Sequence to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writePerFrameFG(DcmItem& dataset); + + /** Convert a shared functional group to a per-frame one by copying the + * shared one into a per-frame one for each frame and deleting the shared one + * aftewrards. + * @param fgType The type of functional group to convert + * @return EC_Normal if conversion worked out, FG_EC_NoSuchGroup if such a + * group does not exist and other error otherwise. In the last case + * the functional groups may be left in invalid state, but that + * should only happen for fatal errors like exhausted memory. + */ + virtual OFCondition convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType); private: + /// Shared functional groups + FunctionalGroups m_shared; - /// Shared functional groups - FunctionalGroups m_shared; - - /// Link from frame number (map key) to the list of functional groups (value) - /// relevant for the frame - PerFrameGroups m_perFrame; + /// Link from frame number (map key) to the list of functional groups (value) + /// relevant for the frame + PerFrameGroups m_perFrame; - /// If enabled, functional group structure is checked on write(). Otherwise, - /// checks are skipped. - OFBool m_checkOnWrite; + /// If enabled, functional group structure is checked on write(). Otherwise, + /// checks are skipped. + OFBool m_checkOnWrite; }; #endif // MODMULTIFRAMEFGH_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h b/dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h new file mode 100644 index 00000000..5c1a820b --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Irradiation Event Identification Functional Group + * + */ + +#ifndef FGIRRADIATIONEVENTID_H +#define FGIRRADIATIONEVENTID_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" + +/** Class representing the "Irradiation Event Identification" Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGIrradiationEventIdentification : public FGBase +{ +public: + /** Constructor, creates empty functional group + */ + FGIrradiationEventIdentification(); + + /** Virtual destructor + */ + virtual ~FGIrradiationEventIdentification(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared functional group type (always "per-frame") + * @return The functional group type (DcmFGTypes::EFGS_ONLYPERFRAME) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this group is consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read Frame Content Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into Frame Content Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Irradiation Event UID + * @param value Reference to variable that should hold the result + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getIrradiationEventUID(OFString& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Irradiation Event UID + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setIrradiationEventUID(const OFString& value, const OFBool checkValue = OFTrue); + +private: + /* Content of Irradiation Event Identification FG */ + + /// Irradiation Event UID (UI, VM 1, Required type 1) + DcmUniqueIdentifier m_IrraditionEventUID; +}; + +#endif // FGIRRADIATIONEVENTID_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgparametricmapframetype.h b/dcmfg/include/dcmtk/dcmfg/fgparametricmapframetype.h index fd463464..b059d466 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgparametricmapframetype.h +++ b/dcmfg/include/dcmtk/dcmfg/fgparametricmapframetype.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,102 +23,103 @@ #define FGPARAMETRICMAPFRAMETYPE_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmfg/fgbase.h" #include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmfg/fgbase.h" /** Class representing the Parametric Map Frame Type Functional Group Macro. */ class DCMTK_DCMFG_EXPORT FGParametricMapFrameType : public FGBase { public: - /** Constructor, creates empty Parametric Map Frame Type Functional Group - */ - FGParametricMapFrameType(); - - /** Destructor, frees memory - */ - virtual ~FGParametricMapFrameType(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Get shared type of this functional group (can be both, per-frame and - * shared) - * @return Always returns EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether functional group contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from given item, i.e.\ read Parametric Map Frame Type Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to given item, i.e.\ write Parametric Map Frame Type Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get FrameType - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFrameType(OFString &value, - const signed long pos = 0) const; - - /** Set FrameType - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (4) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setFrameType(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty Parametric Map Frame Type Functional Group + */ + FGParametricMapFrameType(); + + /** Destructor, frees memory + */ + virtual ~FGParametricMapFrameType(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read Parametric Map Frame Type Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write Parametric Map Frame Type Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get FrameType + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFrameType(OFString& value, const signed long pos = 0) const; + + /** Set FrameType + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (4) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFrameType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Parametric Map Frame Type Functional Group Macro */ - /* Content of Parametric Map Frame Type Functional Group Macro */ - - /// FrameType (CS, VM 4, Required type 1) - DcmCodeString m_FrameType; + /// FrameType (CS, VM 4, Required type 1) + DcmCodeString m_FrameType; }; #endif // FGPARAMETRICMAPFRAMETYPE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h b/dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h index d98771fa..5cf8e87a 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h +++ b/dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2017, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,165 +23,204 @@ #define FGPIXELTRANSFORM_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmfg/fgbase.h" #include "dcmtk/dcmdata/dcvrds.h" #include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmfg/fgbase.h" - -/** Class representing the Identity Pixel Value Transformation as well as the - * Pixel Value Transformation Functional Group Macro. - * The former just differs in a way that Rescale Slope, Intercept and Type - * have fixed values (1, 0 and "US" respectively). - * Rescale Intercept to 0. Right now the +/** Class representing different flavors of the Pixel Value Transformation FG: + * - Pixel Value Transformation + * - Identity Pixel Value Transformation + * - CT Pixel Value Transformation + * The attributes in each type are always the same. + * Value checking is performed if possible for the selected FG type. + * Otherwise only logging is adapted where applicable. */ class DCMTK_DCMFG_EXPORT FGPixelValueTransformation : public FGBase { public: - - /** Constructor, creates (Identity) Pixel Value Transformation Functional Group. - * All values (Rescale Slope, Intercept and Type) are initialized as if the - * class is used as the Identity Pixel Value Transformation FG, i.e. Rescale - * Slope is set to 1, Intercept to 0 and Type to "US". - */ + /// Enumerated values for the type of functional group that this + /// class should represent. + enum E_PixelValueTransformationSubType + { + /// Value representing the "Pixel Value Transformation Functional Group Macro" + E_PixelValTrans_Normal, + /// Value representing the "Identity Pixel Value Transformation Functional Group Macro" + E_PixelValTrans_Identity, + /// Value representing the "CT Pixel Value Transformation Functional Group Macro" + E_PixelValTrans_CT + }; + + /** Constructor, creates (Identity) Pixel Value Transformation Functional Group. + * All values (Rescale Slope, Intercept and Type) are initialized as if the + * class is used as the Identity Pixel Value Transformation FG, i.e. Rescale + * Slope is set to 1, Intercept to 0 and Type to "US". + */ FGPixelValueTransformation(); - /** Destructor, frees memory - */ - virtual ~FGPixelValueTransformation(); - - /** Tell this class that it should behave like the Identity Pixel Value - * Transformation Functional Group. This does not make a difference when - * reading data, but when writing, it is assured that Rescale Slope, - * Intercept and Type are forced to be set to 1, 0 and "US" respectively. - */ - virtual void setUseAsIdentityPixelValueTransformation(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Get shared type of this functional group (can be both, per-frame and - * shared) - * @return Always returns EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether functional group contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from given item, i.e.\ read (Identity) Pixel Value - * Transformation Sequence. Clears existing data before reading. - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to given item, i.e.\ write (Identity) Pixel Value - * Transformation Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get RescaleIntercept - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRescaleIntercept(OFString &value, - const signed long pos = 0) const; - - /** Get RescaleSlope - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRescaleSlope(OFString &value, - const signed long pos = 0) const; - - /** Get RescaleType - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRescaleType(OFString &value, - const signed long pos = 0) const; - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - /** Set RescaleIntercept - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRescaleIntercept(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set RescaleSlope - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRescaleSlope(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set RescaleType - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRescaleType(const OFString &value, - const OFBool checkValue = OFTrue); + /** Destructor, frees memory + */ + virtual ~FGPixelValueTransformation(); + + /** This method is deprecated, use setFGType instead. + * + * Tell this class that it should behave like the Identity Pixel Value + * Transformation Functional Group. This does not make a difference when + * reading data, but when writing, it is assured that Rescale Slope, + * Intercept and Type are forced to be set to 1, 0 and "US" respectively. + */ + virtual void setUseAsIdentityPixelValueTransformation(); + + /** Tell this class as which type of functional group it should behave. + * Transformation Functional Group. This does not make a difference when + * reading or writing data, but the component name is written correctly + * for all corresponding log messages. + * @param fgType Denotes which Functional Group Macro should be represented + * by this class. + */ + virtual void setFGType(const E_PixelValueTransformationSubType fgType); + + /** Get type Functional Group represented by this class. + * @return Type of functional group represented by this class + */ + virtual E_PixelValueTransformationSubType getFGType() const; + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read (Identity) Pixel Value + * Transformation Sequence. Clears existing data before reading. + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write (Identity) Pixel Value + * Transformation Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get RescaleIntercept + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleIntercept(OFString& value, const signed long pos = 0) const; + + /** Get RescaleSlope + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleSlope(OFString& value, const signed long pos = 0) const; + + /** Get RescaleType + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleType(OFString& value, const signed long pos = 0) const; + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Set RescaleIntercept + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRescaleIntercept(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set RescaleSlope + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRescaleSlope(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set RescaleType + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRescaleType(const OFString& value, const OFBool checkValue = OFTrue); + +protected: + /** Returns String denoting the type of functional group represented by this class + * @return String denoting the type of functional group + */ + virtual OFString fgType2Str(); private: - - /* Content of Identity Pixel Value Transformation Functional Group Macro */ - - /// RescaleIntercept (DS, VM 1, Required type 1) - DcmDecimalString m_RescaleIntercept; - - /// RescaleSlope (DS, VM 1, Required type 1) - DcmDecimalString m_RescaleSlope; - - /// RescaleType (LO, VM 1, Required type 1) - DcmLongString m_RescaleType; - - /// If OFTrue, tells this class that it should behave like the Identity Pixel - /// Value Transformation Functional Group. This does not make a difference when - /// reading data, but when writing, it is assured that Rescale Slope, - /// Intercept and Type are forced to be set to 1, 0 and "US" respectively. - OFBool m_UseAsIdentityPixelValueTransformationFG; + /* Content of Identity Pixel Value Transformation Functional Group Macro */ + + /// RescaleIntercept (DS, VM 1, Required type 1) + DcmDecimalString m_RescaleIntercept; + + /// RescaleSlope (DS, VM 1, Required type 1) + DcmDecimalString m_RescaleSlope; + + /// RescaleType (LO, VM 1, Required type 1) + DcmLongString m_RescaleType; + + /// Denotes the represented functional group type. + /// + /// E_PixelValTrans_Normal: Normal Pixel Value Transformation FG. + /// No no special value requirements. + /// E_PixelValTrans_Identity: Identity Pixel Value Transformation FG. + /// Tells this class that it should behave like the Identity Pixel + /// Value Transformation FG. This does not make a difference when + /// reading data, but when writing, it is assured that Rescale Slope, + /// Intercept and Type are forced to be set to 1, 0 and "US" respectively. + /// E_PixelValTrans_CT: CT Pixel Value Transformation FG. + /// Tells this class that it should behave like the CT Pixel + /// Value Transformation FG. No special value requirements. + E_PixelValueTransformationSubType m_fgSubType; }; #endif // FGPIXELTRANSFORM_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h b/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h index 72f43f12..f2a053eb 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h +++ b/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGPIXMSR_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmdata/dcvrds.h" #include "dcmtk/dcmfg/fgbase.h" @@ -32,139 +33,133 @@ class DCMTK_DCMFG_EXPORT FGPixelMeasures : public FGBase { public: - - /** Constructor, creates empty Pixel Measures Functional Group - */ - FGPixelMeasures(); - - /** Virtual destructor, frees memory - */ - virtual ~FGPixelMeasures(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - - /** Returns shared type of this group (can be shared or per-frame) - * @return Always returns DcmFGTypes::EFGS_BOTH; - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether data in functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from given item - * @param item The item to read from, must contain Pixel Measures Sequence - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to given item - * @param item The item to write Pixel Measures Sequence to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Pixel Spacing - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPixelSpacing(Float64& value, - const signed long pos = 0); - - /** Get Slice Thickness - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSliceThickness(Float64& value, - const signed long pos = 0); - - /** Get Spacing Between Slices - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSpacingBetweenSlices(Float64& value, - const signed long pos = 0); - - // --- set() functionality --- - - /** Set Pixel Spacing - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (2) if - * enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPixelSpacing(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Slice Thickness - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if - * enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSliceThickness(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Spacing between Slices - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if - * enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSpacingBetweenSlices(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty Pixel Measures Functional Group + */ + FGPixelMeasures(); + + /** Virtual destructor, frees memory + */ + virtual ~FGPixelMeasures(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared type of this group (can be shared or per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH; + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data in functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item + * @param item The item to read from, must contain Pixel Measures Sequence + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item + * @param item The item to write Pixel Measures Sequence to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Pixel Spacing + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelSpacing(Float64& value, const unsigned long pos = 0); + + /** Get Slice Thickness + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSliceThickness(Float64& value, const unsigned long pos = 0); + + /** Get Spacing Between Slices + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSpacingBetweenSlices(Float64& value, const unsigned long pos = 0); + + // --- set() functionality --- + + /** Set Pixel Spacing + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (2) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelSpacing(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Slice Thickness + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSliceThickness(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Spacing between Slices + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSpacingBetweenSlices(const OFString& value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Pixel Measures Macro */ - /* Content of Pixel Measures Macro */ - - /// Pixel Spacing (DS, VM 2, Required type 1C) - DcmDecimalString m_PixelSpacing; + /// Pixel Spacing (DS, VM 2, Required type 1C) + DcmDecimalString m_PixelSpacing; - /// Slice Thickness (DS, VM 1, Required type 1C) - DcmDecimalString m_SliceThickness; + /// Slice Thickness (DS, VM 1, Required type 1C) + DcmDecimalString m_SliceThickness; - /// Spacing Between Slices (DS, VM 1, Required type 3) - DcmDecimalString m_SpacingBetweenSlices; + /// Spacing Between Slices (DS, VM 1, Required type 3) + DcmDecimalString m_SpacingBetweenSlices; }; #endif // FGPIXMSRS_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanor.h b/dcmfg/include/dcmtk/dcmfg/fgplanor.h index 2b8de192..6ffb3df0 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgplanor.h +++ b/dcmfg/include/dcmtk/dcmfg/fgplanor.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,9 +23,10 @@ #define FGPLANOR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgbase.h" + #include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmfg/fgbase.h" /** Class representing the Plane Orientation (Patient) Functional Group Macro. * It specifies the direction cosines of the first row and the first column @@ -34,142 +35,138 @@ class DCMTK_DCMFG_EXPORT FGPlaneOrientationPatient : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGPlaneOrientationPatient(); - - /** Destructor, frees memory - */ - virtual ~FGPlaneOrientationPatient(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Convenience function to create a minimal functional group. - * @param imageOrientationPatientRowX Row X Value - * @param imageOrientationPatientRowY Row Y Value - * @param imageOrientationPatientRowZ Row Z Value - * @param imageOrientationPatientColX Column X Value - * @param imageOrientationPatientColY Column Y Value - * @param imageOrientationPatientColZ Column Z Value - * @return The functional group created with above parameters - */ - static FGPlaneOrientationPatient* createMinimal(const OFString& imageOrientationPatientRowX, - const OFString& imageOrientationPatientRowY, - const OFString& imageOrientationPatientRowZ, - const OFString& imageOrientationPatientColX, - const OFString& imageOrientationPatientColY, - const OFString& imageOrientationPatientColZ); - - /** Get shared type of this functional group (can be both, shared and - * per-frame) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether this group contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from item, must contain the Plane Orientation - * Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Writes functional group to given item (will write Plane Orientation - * Sequence to it) - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - // --- get() functionality --- - - /** Get Image Orientation Patient - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageOrientationPatient(OFString& value, - const signed long pos); - - /** Retrieve all values of Image Orientation Patient at the same time - * @param rowX Row X Value - * @param rowY Row Y Value - * @param rowZ Row Z Value - * @param colX Column X Value - * @param colY Column Y Value - * @param colZ Column Z Value - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageOrientationPatient(Float64& rowX, - Float64& rowY, - Float64& rowZ, - Float64& colX, - Float64& colY, - Float64& colZ); - - // --- set() functionality --- - - /** Set all values of Image Orientation Patient at once - * @param rowX Row X Value - * @param rowY Row Y Value - * @param rowZ Row Z Value - * @param colX Column X Value - * @param colY Column Y Value - * @param colZ Column Z Value - * @param checkValue If OFTrue, values are checked for validity - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImageOrientationPatient(const OFString& rowX, - const OFString& rowY, - const OFString& rowZ, - const OFString& colX, - const OFString& colY, - const OFString& colZ, - const OFBool checkValue = OFTrue); + /** Constructor, creates empty functional group + */ + FGPlaneOrientationPatient(); + + /** Destructor, frees memory + */ + virtual ~FGPlaneOrientationPatient(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Convenience function to create a minimal functional group. + * @param imageOrientationPatientRowX Row X Value + * @param imageOrientationPatientRowY Row Y Value + * @param imageOrientationPatientRowZ Row Z Value + * @param imageOrientationPatientColX Column X Value + * @param imageOrientationPatientColY Column Y Value + * @param imageOrientationPatientColZ Column Z Value + * @return The functional group created with above parameters + */ + static FGPlaneOrientationPatient* createMinimal(const OFString& imageOrientationPatientRowX, + const OFString& imageOrientationPatientRowY, + const OFString& imageOrientationPatientRowZ, + const OFString& imageOrientationPatientColX, + const OFString& imageOrientationPatientColY, + const OFString& imageOrientationPatientColZ); + + /** Get shared type of this functional group (can be both, shared and + * per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether this group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Orientation + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes functional group to given item (will write Plane Orientation + * Sequence to it) + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Image Orientation Patient + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationPatient(OFString& value, const signed long pos); + + /** Retrieve all values of Image Orientation Patient at the same time + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationPatient( + Float64& rowX, Float64& rowY, Float64& rowZ, Float64& colX, Float64& colY, Float64& colZ); + + // --- set() functionality --- + + /** Set all values of Image Orientation Patient at once + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @param checkValue If OFTrue, values are checked for validity + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageOrientationPatient(const OFString& rowX, + const OFString& rowY, + const OFString& rowZ, + const OFString& colX, + const OFString& colY, + const OFString& colZ, + const OFBool checkValue = OFTrue); private: + /* Content of Plane Orientation (Patient) Macro */ - /* Content of Plane Orientation (Patient) Macro */ - - /// Image Orientation (Patient) (DS, VM 6, Required type 1C) - DcmDecimalString m_ImageOrientationPatient; + /// Image Orientation (Patient) (DS, VM 6, Required type 1C) + DcmDecimalString m_ImageOrientationPatient; }; #endif // FGPLANOR_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h b/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h index 16729c94..73ad23d5 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h +++ b/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGPLANORVOL_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgbase.h" @@ -33,127 +34,123 @@ class DCMTK_DCMFG_EXPORT FGPlaneOrientationVolume : public FGBase { public: - - /** Constructor, creates empty Plane Orientation (Volume) Functional Group - */ - FGPlaneOrientationVolume(); - - /** Destructor, frees memory - */ - virtual ~FGPlaneOrientationVolume(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Get shared type of this functional group (can be both, per-frame and - * shared) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether functional group contains valid data - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from given item, i.e.\ read Plane Orientation - * (Volume) Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to given item, i.e.\ write Plane Orientation - * (Volume) Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Image Orientation Volume - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageOrientationVolume(Float64& value, - const unsigned long pos = 0); - - /** Retrieve all values of Image Orientation Volume at the same time - * @param rowX Row X Value - * @param rowY Row Y Value - * @param rowZ Row Z Value - * @param colX Column X Value - * @param colY Column Y Value - * @param colZ Column Z Value - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageOrientationVolume(Float64& rowX, - Float64& rowY, - Float64& rowZ, - Float64& colX, - Float64& colY, - Float64& colZ); - - // --- set() functionality --- - - /** Set all values of Image Orientation Volume at once - * @param rowX Row X Value - * @param rowY Row Y Value - * @param rowZ Row Z Value - * @param colX Column X Value - * @param colY Column Y Value - * @param colZ Column Z Value - * @param checkValue If OFTrue, values are checked for validity (not - * implemented yet) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImageOrientationVolume(const Float64& rowX, - const Float64& rowY, - const Float64& rowZ, - const Float64& colX, - const Float64& colY, - const Float64& colZ, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty Plane Orientation (Volume) Functional Group + */ + FGPlaneOrientationVolume(); + + /** Destructor, frees memory + */ + virtual ~FGPlaneOrientationVolume(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read Plane Orientation + * (Volume) Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write Plane Orientation + * (Volume) Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Image Orientation Volume + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationVolume(Float64& value, const unsigned long pos = 0); + + /** Retrieve all values of Image Orientation Volume at the same time + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + getImageOrientationVolume(Float64& rowX, Float64& rowY, Float64& rowZ, Float64& colX, Float64& colY, Float64& colZ); + + // --- set() functionality --- + + /** Set all values of Image Orientation Volume at once + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @param checkValue If OFTrue, values are checked for validity (not + * implemented yet) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageOrientationVolume(const Float64& rowX, + const Float64& rowY, + const Float64& rowZ, + const Float64& colX, + const Float64& colY, + const Float64& colZ, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Plane Orientation (Volume) Macro */ - /* Content of Plane Orientation (Volume) Macro */ - - /// Image Orientation (Volume) (FD, VM 6, Required type 1) - DcmFloatingPointDouble m_ImageOrientationVolume; + /// Image Orientation (Volume) (FD, VM 6, Required type 1) + DcmFloatingPointDouble m_ImageOrientationVolume; }; #endif // FGPLANORVOL_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanpo.h b/dcmfg/include/dcmtk/dcmfg/fgplanpo.h index 1fcf2a21..c2557d60 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgplanpo.h +++ b/dcmfg/include/dcmtk/dcmfg/fgplanpo.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,9 +23,10 @@ #define FGPLANPO_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgbase.h" + #include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmfg/fgbase.h" /** Class representing the Plane Position (Patient) Functional Group containing * the x, y, and z coordinates of the upper left hand corner (center of the @@ -34,124 +35,123 @@ class DCMTK_DCMFG_EXPORT FGPlanePosPatient : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGPlanePosPatient(); - - /** Destructor, frees memory - */ - virtual ~FGPlanePosPatient(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Convenience function to create minimal functional group - * @param imagePositionPatientX The X coordinate of the upper left hand - * corner of the the frame in mm. - * @param imagePositionPatientY The Y coordinate of the upper left hand - * corner of the the frame in mm. - * @param imagePositionPatientZ The Z coordinate of the upper left hand - * corner of the the frame in mm. - */ - static FGPlanePosPatient* createMinimal(const OFString& imagePositionPatientX, - const OFString& imagePositionPatientY, - const OFString& imagePositionPatientZ); - - /** Returns that this functional group can be shared or per-frame (both) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether data in functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from item, must contain the Plane Position Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to item, will write the Plane Position Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - // --- get() functionality --- - - /** Get Image Position Patient - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImagePositionPatient(OFString& value, - const signed long pos); - - /** Retrieve all values of Image Orientation Patient at the same time - * @param coordinateX X coordinate of upper left hand corner voxel in mm - * @param coordinateY Y coordinate of upper left hand corner voxel in mm - * @param coordinateZ Z coordinate of upper left hand corner voxel in mm - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImagePositionPatient(Float64& coordinateX, - Float64& coordinateY, - Float64& coordinateZ); - - // --- set() functionality --- - - /** Set Image Position Patient. The x, y, and z coordinates of the upper left - * hand corner (center of the first voxel transmitted) of the frame, in mm. - * @param coordinateX X coordinate of upper left hand corner voxel in mm - * @param coordinateY Y coordinate of upper left hand corner voxel in mm - * @param coordinateZ Z coordinate of upper left hand corner voxel in mm - * @param checkValue Check coordinates for validity, including VR (DS) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImagePositionPatient(const OFString& coordinateX, - const OFString& coordinateY, - const OFString& coordinateZ, - const OFBool checkValue = OFTrue); + /** Constructor, creates empty functional group + */ + FGPlanePosPatient(); + + /** Destructor, frees memory + */ + virtual ~FGPlanePosPatient(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Convenience function to create minimal functional group + * @param imagePositionPatientX The X coordinate of the upper left hand + * corner of the the frame in mm. + * @param imagePositionPatientY The Y coordinate of the upper left hand + * corner of the the frame in mm. + * @param imagePositionPatientZ The Z coordinate of the upper left hand + * corner of the the frame in mm. + * @return Newly created Plane Position Functional Group or NULL in case of error + */ + static FGPlanePosPatient* createMinimal(const OFString& imagePositionPatientX, + const OFString& imagePositionPatientY, + const OFString& imagePositionPatientZ); + + /** Returns that this functional group can be shared or per-frame (both) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data in functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Position Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to item, will write the Plane Position Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Image Position Patient + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionPatient(OFString& value, const signed long pos); + + /** Retrieve all values of Image Orientation Patient at the same time + * @param coordinateX X coordinate of upper left hand corner voxel in mm + * @param coordinateY Y coordinate of upper left hand corner voxel in mm + * @param coordinateZ Z coordinate of upper left hand corner voxel in mm + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionPatient(Float64& coordinateX, Float64& coordinateY, Float64& coordinateZ); + + // --- set() functionality --- + + /** Set Image Position Patient. The x, y, and z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param coordinateX X coordinate of upper left hand corner voxel in mm + * @param coordinateY Y coordinate of upper left hand corner voxel in mm + * @param coordinateZ Z coordinate of upper left hand corner voxel in mm + * @param checkValue Check coordinates for validity, including VR (DS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImagePositionPatient(const OFString& coordinateX, + const OFString& coordinateY, + const OFString& coordinateZ, + const OFBool checkValue = OFTrue); private: + /* Content of Plane Position Patient Macro */ - /* Content of Plane Position Patient Macro */ - - /// Image Position (Patient) (DS, VM 3, Required type 1C) - DcmDecimalString m_ImagePositionPatient; + /// Image Position (Patient) (DS, VM 3, Required type 1C) + DcmDecimalString m_ImagePositionPatient; }; #endif // FGPLANPO_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h b/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h index 40086ca8..037fb125 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h +++ b/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGPLANEPOSVOL_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgbase.h" @@ -32,128 +33,125 @@ class DCMTK_DCMFG_EXPORT FGPlanePositionVolume : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGPlanePositionVolume(); - - /** Virtual destructor, frees memory - */ - virtual ~FGPlanePositionVolume(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Returns shared type of this functional group (can be shared or per-frame, - * i.e.\ both) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether data of this functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from item, must contain the Plane Position (Volume) - * Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Writes functional group to item, i.e.\ writes the Plane Position (Volume) - * Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Get Image Position Volume - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImagePositionVolume(Float64& value, - const unsigned long pos = 0); - - /** Retrieve all values of Image Position Volume at the same time - * @param valueX X coordinate of upper left hand corner voxel in mm - * @param valueY Y coordinate of upper left hand corner voxel in mm - * @param valueZ Z coordinate of upper left hand corner voxel in mm - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImagePositionVolume(Float64& valueX, - Float64& valueY, - Float64& valueZ); - - // --- set() functionality --- - - /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left - * hand corner (center of the first voxel transmitted) of the frame, in mm. - * @param value X,Y or Z coordinate of upper left hand corner voxel in mm - * @param pos pos 0 is x, pos 1 is Y, pos 2 addresses Z coordinate - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImagePositionVolume(const Float64& value, - const unsigned long pos = 0, - const OFBool checkValue = OFTrue); - - /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left - * hand corner (center of the first voxel transmitted) of the frame, in mm. - * @param valueX X coordinate of upper left hand corner voxel in mm - * @param valueY coordinate of upper left hand corner voxel in mm - * @param valueZ coordinate of upper left hand corner voxel in mm - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImagePositionVolume(const Float64& valueX, - const Float64& valueY, - const Float64& valueZ, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty functional group + */ + FGPlanePositionVolume(); + + /** Virtual destructor, frees memory + */ + virtual ~FGPlanePositionVolume(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns shared type of this functional group (can be shared or per-frame, + * i.e.\ both) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data of this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Position (Volume) + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes functional group to item, i.e.\ writes the Plane Position (Volume) + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Image Position Volume + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionVolume(Float64& value, const unsigned long pos = 0); + + /** Retrieve all values of Image Position Volume at the same time + * @param valueX X coordinate of upper left hand corner voxel in mm + * @param valueY Y coordinate of upper left hand corner voxel in mm + * @param valueZ Z coordinate of upper left hand corner voxel in mm + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionVolume(Float64& valueX, Float64& valueY, Float64& valueZ); + + // --- set() functionality --- + + /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param value X,Y or Z coordinate of upper left hand corner voxel in mm + * @param pos pos 0 is x, pos 1 is Y, pos 2 addresses Z coordinate + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setImagePositionVolume(const Float64& value, const unsigned long pos = 0, const OFBool checkValue = OFTrue); + + /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param valueX X coordinate of upper left hand corner voxel in mm + * @param valueY coordinate of upper left hand corner voxel in mm + * @param valueZ coordinate of upper left hand corner voxel in mm + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImagePositionVolume(const Float64& valueX, + const Float64& valueY, + const Float64& valueZ, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Plane Position (Volume) Macro */ - /* Content of Plane Position (Volume) Macro */ - - /// Image Position (Volume) (FD, VM 3, Required type 1) - DcmFloatingPointDouble m_ImagePositionVolume; + /// Image Position (Volume) (FD, VM 3, Required type 1) + DcmFloatingPointDouble m_ImagePositionVolume; }; #endif // FGPLANEPOSVOL_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h b/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h index 27545f9f..c734364f 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h +++ b/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,103 +23,105 @@ #define FGREALWORLDVALUEMAPPING_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgbase.h" + #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmiod/modbase.h" -#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmfg/fgbase.h" #include "dcmtk/dcmiod/iodcontentitemmacro.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modbase.h" /** Class representing the Real World Value Mapping Functional Group that * specifies the mapping of stored values to associated Real World values */ -class DCMTK_DCMFG_EXPORT FGRealWorldValueMapping: public FGBase +class DCMTK_DCMFG_EXPORT FGRealWorldValueMapping : public FGBase { public: - - // Forward declaration - class RWVMItem; - - /** Constructor, creates empty functional group - */ - FGRealWorldValueMapping(); - - /** Destructor, frees memory - */ - virtual ~FGRealWorldValueMapping(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Returns that this functional group can be used as both, shared - * and per-frame - * @returns Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether data of functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from item, must contain the Real World Value Mapping - * Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Writes this functional group to item, i.e.\ will write the Real World Value - * Mapping Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - // --- get() functionality --- - - /** Return references to the various items inside the Real World Value Mapping - * Sequence - * @return Reference to Real World Value Mapping Sequence items - */ - virtual OFVector< RWVMItem* >& getRealWorldValueMapping(); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + // Forward declaration + class RWVMItem; + + /** Constructor, creates empty functional group + */ + FGRealWorldValueMapping(); + + /** Destructor, frees memory + */ + virtual ~FGRealWorldValueMapping(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns that this functional group can be used as both, shared + * and per-frame + * @returns Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data of functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Real World Value Mapping + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes this functional group to item, i.e.\ will write the Real World Value + * Mapping Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Return references to the various items inside the Real World Value Mapping + * Sequence + * @return Reference to Real World Value Mapping Sequence items + */ + virtual OFVector& getRealWorldValueMapping(); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of Real World Value Mapping Macro */ - /* Content of Real World Value Mapping Macro */ - - /// Items (1-n) of Real World Value Mapping Sequence - OFVector m_Items; + /// Items (1-n) of Real World Value Mapping Sequence + OFVector m_Items; }; /** Class representing the Real World Value Mapping Item Macro: @@ -137,284 +139,259 @@ private: class DCMTK_DCMFG_EXPORT FGRealWorldValueMapping::RWVMItem : public IODComponent { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - RWVMItem(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - RWVMItem(IODComponent* parent = NULL); - - /** Copy Constructor - * @param rhs The item to copy from - */ - RWVMItem(const RWVMItem& rhs); - - /** Clone this class (perform deep copy) - * @return Clone of this class or NULL (e.g.\ if memory exhausted) - */ - RWVMItem* clone(); - - /** Virtual destructor, frees memory - */ - virtual ~RWVMItem(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of component - * @return Name of the module - */ - virtual OFString getName() const; - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const IODComponent& rhs) const; - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. - * Otherwise old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - // --- get() functionality --- - - /** Get Real World Value First Value Mapped - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRealWorldValueFirstValueMapped(Sint32& value, - const unsigned long pos = 0) const; - - /** Get Real World Value First Value Mapped - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRealWorldValueLastValueMapped(Sint32 &value, - const unsigned long pos = 0) const; - - /** Get Double Float Real World Value First Value Mapped - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDoubleFloatRealWorldValueFirstValueMapped(Float64& value, - const unsigned long pos = 0) const; - - /** Get Double Float Real World Value Last Value Mapped - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDoubleFloatRealWorldValueLastValueMapped(Float64& value, - const unsigned long pos = 0) const; - - /** Get Real World Value LUT Data - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRealWorldValueLUTData(Float64 &value, - const unsigned long pos = 0) const; - - /** Get Real World Value LUT Data - * @param values Reference to variable in which the values should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRealWorldValueLUTData(OFVector& values) const; - - /** Get LUT Explanation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLUTExplanation(OFString &value, - const signed long pos = 0) const; - - /** Get LUT Label - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLUTLabel(OFString &value, - const signed long pos = 0) const; - - /** Get Measurement Units Code Sequence (content) - * @return Reference to Measurement Units Code - */ - virtual CodeSequenceMacro& getMeasurementUnitsCode(); - - /** Get a reference to the entire ConceptNameCodeSequence, including items - * exceeding the value multiplicity restriction of "1" - * @return a reference to the entire ConceptNameCodeSequence - */ - virtual OFVector& getEntireQuantityDefinitionSequence(); - - // --- set() functionality --- - - /** Set Real World Value First Value Mapped - * @param value Value to be set. If Pixel Representation is 0 (unsigned - * pixel data) value must be 0 < value < 2^16. Otherwise use - * setRealWorldValueFirstValueMappedSigned(). - * @param checkValue Check 'value' for conformance with VR (US and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueFirstValueMappedUnsigned(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value First Value Mapped - * @param value Value to be set. If Pixel Representation is -1 (signed - * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use - * setRealWorldValueFirstValueMappedUnsigned(). - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueFirstValueMappedSigned(const Sint16 &value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value Last Value Mapped - * @param value Value to be set. If Pixel Representation is 0 (unsigned - * pixel data) value must be 0 < value < 2^16. Otherwise use - * setRealWorldValueLastValueMappedSigned(). - * @param checkValue Check 'value' for conformance with VR (US and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueLastValueMappedUnsigned(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value Last Value Mapped - * @param value Value to be set. If Pixel Representation is -1 (signed - * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use - * setRealWorldValueLastValueMappedUnsigned(). - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueLastValueMappedSigned(const Sint16 &value, - const OFBool checkValue = OFTrue); - - /** Set Double Float Real World Value First Value Mapped - * @param value Value to be set - * @param checkValue Check 'value'. Does nothing, only for consistency with - * other set() functions. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDoubleFloatRealWorldValueFirstValueMapped(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Double Float Real World Value Last Value Mapped - * @param value Value to be set - * @param checkValue Check 'value'. Does nothing, only for consistency with - * other set() functions. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDoubleFloatRealWorldValueLastValueMapped(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value Intercept - * @param value Value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueIntercept(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value Slope - * @param value Value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueSlope(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Real World Value LUT Data - * @param value Values to be set - * @param checkValue Check 'value' for conformance with VR (FD) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRealWorldValueLUTData(const OFVector& value, - const OFBool checkValue = OFTrue); - - /** Set LUT Explanation - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLUTExplanation(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set LUT Label - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLUTLabel(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + RWVMItem(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + RWVMItem(IODComponent* parent = NULL); + + /** Copy Constructor + * @param rhs The item to copy from + */ + RWVMItem(const RWVMItem& rhs); + + /** Clone this class (perform deep copy) + * @return Clone of this class or NULL (e.g.\ if memory exhausted) + */ + RWVMItem* clone(); + + /** Virtual destructor, frees memory + */ + virtual ~RWVMItem(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of component + * @return Name of the module + */ + virtual OFString getName() const; + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const IODComponent& rhs) const; + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. + * Otherwise old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + // --- get() functionality --- + + /** Get Real World Value First Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueFirstValueMapped(Sint32& value, const unsigned long pos = 0) const; + + /** Get Real World Value First Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLastValueMapped(Sint32& value, const unsigned long pos = 0) const; + + /** Get Double Float Real World Value First Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDoubleFloatRealWorldValueFirstValueMapped(Float64& value, const unsigned long pos = 0) const; + + /** Get Double Float Real World Value Last Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDoubleFloatRealWorldValueLastValueMapped(Float64& value, const unsigned long pos = 0) const; + + /** Get Real World Value LUT Data + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLUTData(Float64& value, const unsigned long pos = 0) const; + + /** Get Real World Value LUT Data + * @param values Reference to variable in which the values should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLUTData(OFVector& values) const; + + /** Get LUT Explanation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLUTExplanation(OFString& value, const signed long pos = 0) const; + + /** Get LUT Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLUTLabel(OFString& value, const signed long pos = 0) const; + + /** Get Measurement Units Code Sequence (content) + * @return Reference to Measurement Units Code + */ + virtual CodeSequenceMacro& getMeasurementUnitsCode(); + + /** Get a reference to the entire ConceptNameCodeSequence, including items + * exceeding the value multiplicity restriction of "1" + * @return a reference to the entire ConceptNameCodeSequence + */ + virtual OFVector& getEntireQuantityDefinitionSequence(); + + // --- set() functionality --- + + /** Set Real World Value First Value Mapped + * @param value Value to be set. If Pixel Representation is 0 (unsigned + * pixel data) value must be 0 < value < 2^16. Otherwise use + * setRealWorldValueFirstValueMappedSigned(). + * @param checkValue Check 'value' for conformance with VR (US and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueFirstValueMappedUnsigned(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Real World Value First Value Mapped + * @param value Value to be set. If Pixel Representation is -1 (signed + * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use + * setRealWorldValueFirstValueMappedUnsigned(). + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueFirstValueMappedSigned(const Sint16& value, const OFBool checkValue = OFTrue); + + /** Set Real World Value Last Value Mapped + * @param value Value to be set. If Pixel Representation is 0 (unsigned + * pixel data) value must be 0 < value < 2^16. Otherwise use + * setRealWorldValueLastValueMappedSigned(). + * @param checkValue Check 'value' for conformance with VR (US and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLastValueMappedUnsigned(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Real World Value Last Value Mapped + * @param value Value to be set. If Pixel Representation is -1 (signed + * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use + * setRealWorldValueLastValueMappedUnsigned(). + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLastValueMappedSigned(const Sint16& value, const OFBool checkValue = OFTrue); + + /** Set Double Float Real World Value First Value Mapped + * @param value Value to be set + * @param checkValue Check 'value'. Does nothing, only for consistency with + * other set() functions. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDoubleFloatRealWorldValueFirstValueMapped(const Float64 value, + const OFBool checkValue = OFTrue); + + /** Set Double Float Real World Value Last Value Mapped + * @param value Value to be set + * @param checkValue Check 'value'. Does nothing, only for consistency with + * other set() functions. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDoubleFloatRealWorldValueLastValueMapped(const Float64 value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value Intercept + * @param value Value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueIntercept(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Real World Value Slope + * @param value Value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueSlope(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Real World Value LUT Data + * @param value Values to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLUTData(const OFVector& value, const OFBool checkValue = OFTrue); + + /** Set LUT Explanation + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLUTExplanation(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set LUT Label + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLUTLabel(const OFString& value, const OFBool checkValue = OFTrue); protected: - - static OFCondition getUSorSS(DcmItem& item, - const DcmTagKey& key, - const unsigned long pos, - Sint32& value); + static OFCondition getUSorSS(DcmItem& item, const DcmTagKey& key, const unsigned long pos, Sint32& value); private: + /// The name of this module ("RealWorldValueMappingItemMacro") + static const OFString m_ModuleName; - /// The name of this module ("RealWorldValueMappingItemMacro") - static const OFString m_ModuleName; - - /// Measurement Units Code Sequence - CodeSequenceMacro m_MeasurementUnitsCode; + /// Measurement Units Code Sequence + CodeSequenceMacro m_MeasurementUnitsCode; - /// Quantity Definition Sequence - OFVector m_QuantityDefinitionSequence; + /// Quantity Definition Sequence + OFVector m_QuantityDefinitionSequence; }; #endif // FGREALWORLDVALUEMAPPING_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgseg.h b/dcmfg/include/dcmtk/dcmfg/fgseg.h index 153e8818..1a060df9 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgseg.h +++ b/dcmfg/include/dcmtk/dcmfg/fgseg.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define FGSEG_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dcvrus.h" @@ -34,95 +35,95 @@ class DCMTK_DCMFG_EXPORT FGSegmentation : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGSegmentation(); - - /** Destructor, frees memory - */ - virtual ~FGSegmentation(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Returns that this functional group can be used shared or per-frame, - * i.e.\ both - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether data in this functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - OFCondition check() const; - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGSegmentation) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const FGBase& rhs) const; - - /** Get Referenced Segment Number - * @param value Reference to variable in which the value should be stored - * @param pos Index value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferencedSegmentNumber(Uint16 &value, - const unsigned long pos = 0); - - /** Set Referenced Segment Number - * @param segmentNumber Value to be set - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setReferencedSegmentNumber(const Uint16 &segmentNumber); - - /** Read functional group from item, must contain the Segment Identification - * Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Write functional group to item, will write Segment Identification - * Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /** Constructor, creates empty functional group + */ + FGSegmentation(); + + /** Destructor, frees memory + */ + virtual ~FGSegmentation(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Returns that this functional group can be used shared or per-frame, + * i.e.\ both + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data in this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + OFCondition check() const; + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGSegmentation) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Get Referenced Segment Number + * @param value Reference to variable in which the value should be stored + * @param pos Index value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSegmentNumber(Uint16& value, const unsigned long pos = 0); + + /** Set Referenced Segment Number + * @param segmentNumber Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferencedSegmentNumber(const Uint16& segmentNumber); + + /** Read functional group from item, must contain the Segment Identification + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to item, will write Segment Identification + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); private: - - /// Referenced Segment Number: (US, 1-n, 1) - /// Represents single value within the single permitted item of the - /// Segment Identification Sequence being the data structure the - /// Segmentation FG is made of. - DcmUnsignedShort m_ReferencedSegmentNumber; + /// Referenced Segment Number: (US, 1-n, 1) + /// Represents single value within the single permitted item of the + /// Segment Identification Sequence being the data structure the + /// Segmentation FG is made of. + DcmUnsignedShort m_ReferencedSegmentNumber; }; #endif // FGSEG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h b/dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h new file mode 100644 index 00000000..73365af5 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h @@ -0,0 +1,130 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Temporal Position Functional Group + * + */ + +#ifndef FGTEMPORALPOSITION_H +#define FGTEMPORALPOSITION_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dctk.h" // TODO: include only needed VRs +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmfg/fgtypes.h" + +/** Class representing the Temporal Position Functional Group Macro. + */ +class DCMTK_DCMFG_EXPORT FGTemporalPosition : public FGBase +{ +public: + /** Constructor, creates empty Temporal Position Functional Group + */ + FGTemporalPosition(); + + /** Destructor, frees memory + */ + virtual ~FGTemporalPosition(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read Temporal Position Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write Temporal Position Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get TemporalPositionTimeOffset + * Time offset of the frame in the set of frames with different temporal positions, in seconds. + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTemporalPositionTimeOffset(Float64& value, const unsigned long pos = 0) const; + + /** Set TemporalPositionTimeOffset + * Time offset of the frame in the set of frames with different temporal positions, in seconds. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTemporalPositionTimeOffset(const Float64& value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +protected: + /* Content of Temporal Position Functional Group Macro */ + + /// TemporalPositionTimeOffset (FD, VM 1, Required type 1) + /// Time offset of the frame in the set of frames with different temporal positions, in seconds. + DcmFloatingPointDouble m_TemporalPositionTimeOffset; +}; + +#endif // FGTEMPORALPOSITION_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgtypes.h b/dcmfg/include/dcmtk/dcmfg/fgtypes.h index f790cb7a..0d19a59e 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgtypes.h +++ b/dcmfg/include/dcmtk/dcmfg/fgtypes.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,9 +23,10 @@ #define FGTYPES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/oflog/oflog.h" + #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/oflog/oflog.h" class FGBase; class FunctionalGroups; @@ -38,19 +39,17 @@ extern DCMTK_DCMFG_EXPORT OFLogger DCM_dcmfgLogger; #define DCMFG_TRACE(msg) OFLOG_TRACE(DCM_dcmfgLogger, msg) #define DCMFG_DEBUG(msg) OFLOG_DEBUG(DCM_dcmfgLogger, msg) -#define DCMFG_INFO(msg) OFLOG_INFO(DCM_dcmfgLogger, msg) -#define DCMFG_WARN(msg) OFLOG_WARN(DCM_dcmfgLogger, msg) +#define DCMFG_INFO(msg) OFLOG_INFO(DCM_dcmfgLogger, msg) +#define DCMFG_WARN(msg) OFLOG_WARN(DCM_dcmfgLogger, msg) #define DCMFG_ERROR(msg) OFLOG_ERROR(DCM_dcmfgLogger, msg) #define DCMFG_FATAL(msg) OFLOG_FATAL(DCM_dcmfgLogger, msg) - // include this file in doxygen documentation /** @file fgtypes.h * @brief type definitions, constants and helper functions for the dcmfg module */ - /*-----------------------* * constant definitions * *-----------------------*/ @@ -61,33 +60,47 @@ extern DCMTK_DCMFG_EXPORT OFLogger DCM_dcmfgLogger; */ /// Functional group already exists -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_DoubledFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_DoubledFG; /// Specified functional group does not exist -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSuchGroup; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSuchGroup; /// Not enough items -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughItems; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughItems; /// Too many Items -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_TooManyItems; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_TooManyItems; /// Invalid data -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_InvalidData; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_InvalidData; /// Could not write functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotWriteFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotWriteFG; /// Could not insert functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotInsertFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotInsertFG; /// No such shared functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSharedFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSharedFG; /// No such per-frame functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoPerFrameFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoPerFrameFG; /// Could not create functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotCreateFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotCreateFG; /// Could not create functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotReadSourceImage; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotReadSourceImage; /// Could not create functional group -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotAddFG; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotAddFG; /// Not enough frames found -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughFrames; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughFrames; /// No stacks specified (but expected) -extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoStacksFound; +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoStacksFound; +/// SOP Class does allow Concatenations +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_SOPClassForbidsConcatenations; +/// Pixel Data is missing +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_PixelDataMissing; +/// Pixel Data dimensions invalid +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_PixelDataDimensionsInvalid; +/// Pixel Data element too large +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_PixelDataTooLarge; +/// Inconsistent Concatenation Data +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_InconsistentConcatenationData; +/// Concatenation Complete - no more data available +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_ConcatenationComplete; +/// Unsupported pixel data layout +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_UnsupportedPixelDataLayout; /*---------------------* * class declaration * @@ -100,120 +113,138 @@ class DCMTK_DCMFG_EXPORT DcmFGTypes { public: - - // --- Type definitions --- - - /** Functional group types - */ - enum E_FGType - { - /// Undefined functional group - EFG_UNDEFINED, - /// Unknown functional group - EFG_UNKNOWN, - /// Cardiac Synchronization - EFG_CARDIACSYNC, - /// Contrast/Bolus Usage - EFG_CONTRASTBOLUSUSAGE, - /// Derivation Image - EFG_DERIVATIONIMAGE, - /// Frame Anatomy - EFG_FRAMEANATOMY, - /// Frame Content - EFG_FRAMECONTENT, - /// Frame Display Shutter - EFG_FRAMEDISPLAYSHUTTER, - /// Frame Pixel Shift - EFG_FRAMEPIXELSHIFT, - /// "Frame VOI LUT" or "Frame VOI LUT with LUT" Macro (share same starting sequence) - EFG_FRAMEVOILUTMETA, - /// Image Data Type - EFG_IMAGEDATATYPE, - /// Irradiation Event Identification - EFG_IRRADIATIONEVENTIDENT, - /// Parametric Map Frame Type - EFG_PARAMETRICMAPFRAMETYPE, - /// Patient Orientation in Frame - EFG_PATIENTORIENTINFRAME, - /// Patient Physiological State - EFG_PATIENTPHYSIOSTATE, - /// Pixel Intensity Relationship LUT - EFG_PIXELINTENSITYRELLUT, - /// Pixel Measures - EFG_PIXELMEASURES, - /// "Pixel Value Transformation" or "Identity Pixel Value Transformation" - /// (both share the same sequence and attributes) - EFG_PIXELVALUETRANSMETA, - /// Plane Orientation (Volume) - EFG_PLANEORIENTVOLUME, - /// Plane Position (Volume) - EFG_PLANEPOSITIONVOLUME, - /// Plane Position (Patient) - EFG_PLANEPOSPATIENT, - /// Plane Orientation (Patient) - EFG_PLANEORIENTPATIENT, - /// Radiopharmaceutical Usage - EFG_RADIOPHARAMAUSAGE, - /// Real World Value Mapping - EFG_REALWORLDVALUEMAPPING, - /// Respiratory Synchronization - EFG_RESPIRATORYSYNC, - /// Segmentation Macro - EFG_SEGMENTATION, - /// Temporal Position Macro - EFG_TEMPORALPOSITION, - /// Unassigned Shared Converted Attributes Macro - EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES, - /// US Image Description Macro - EFG_USIMAGEDESCRIPTION - }; - - /** Functional group types - */ - enum E_FGSharedType - { - /// Unknown - EFGS_UNKNOWN, - /// Functional Group can be shared or per-frame - EFGS_BOTH, - /// Functional Group can only be shared (not per-frame) - EFGS_ONLYSHARED, - /// Functional Group can only be per-frame (not shared) - EFGS_ONLYPERFRAME - }; - - /** US Image Description Frame Type (first value) - */ - enum E_FGUSFrameType - { - /// Unknown - EFGFT_UNKNOWN, - /// ORIGINAL - EFGFT_ORIGINAL, - /// DERIVED - EFGFT_DERIVED - }; - - // -- static helpers -- - - /** Returns functional group type based on tag key - * @param key The key to get the group type for - * @return The functional group type - */ - static E_FGType tagKey2FGType(const DcmTagKey& key); - - /** Returns the name of the functional group based on the group type - * @param fgType The functional group type - * @return The name of the functional group - */ - static OFString FGType2OFString(const E_FGType fgType); - - /** Returns the name of a functional group based on a given tag key - * @param key The tag key to get the functional group type for - * @return The name of the functional group - */ - static OFString tagKey2FGString(const DcmTagKey& key); - + // --- Type definitions --- + + /** Functional group types + */ + enum E_FGType + { + /// Undefined functional group + EFG_UNDEFINED, + /// Unknown functional group + EFG_UNKNOWN, + /// Cardiac Synchronization + EFG_CARDIACSYNC, + /// Contrast/Bolus Usage + EFG_CONTRASTBOLUSUSAGE, + /// CT Acquisition Details + EFG_CTACQUISITIONDETAILS, + /// CT Acquisition Type + EFG_CTACQUISITIONTYPE, + /// CT Additional X-Ray Source + EFG_CTADDITIONALXRAYSOURCE, + /// CT Exposure + EFG_CTEXPOSURE, + /// CT Geometry + EFG_CTGEOMETRY, + /// CT Image Frame Type + EFG_CTIMAGEFRAMETYPE, + /// CT Position + EFG_CTPOSITION, + /// CT Reconstruction + EFG_CTRECONSTRUCTION, + /// CT Table Dynamics + EFG_CTTABLEDYNAMICS, + /// CT X-Ray Details + EFG_CTXRAYDETAILS, + /// Derivation Image + EFG_DERIVATIONIMAGE, + /// Frame Anatomy + EFG_FRAMEANATOMY, + /// Frame Content + EFG_FRAMECONTENT, + /// Frame Display Shutter + EFG_FRAMEDISPLAYSHUTTER, + /// Frame Pixel Shift + EFG_FRAMEPIXELSHIFT, + /// "Frame VOI LUT" or "Frame VOI LUT with LUT" Macro (share same starting sequence) + EFG_FRAMEVOILUTMETA, + /// Image Data Type + EFG_IMAGEDATATYPE, + /// Irradiation Event Identification + EFG_IRRADIATIONEVENTIDENT, + /// Parametric Map Frame Type + EFG_PARAMETRICMAPFRAMETYPE, + /// Patient Orientation in Frame + EFG_PATIENTORIENTINFRAME, + /// Patient Physiological State + EFG_PATIENTPHYSIOSTATE, + /// Pixel Intensity Relationship LUT + EFG_PIXELINTENSITYRELLUT, + /// Pixel Measures + EFG_PIXELMEASURES, + /// "Pixel Value Transformation", "Identity Pixel Value Transformation", or + /// "CT Pixel Value Transformation"; all the same sequence and attributes. + EFG_PIXELVALUETRANSMETA, + /// Plane Orientation (Volume) + EFG_PLANEORIENTVOLUME, + /// Plane Position (Volume) + EFG_PLANEPOSITIONVOLUME, + /// Plane Position (Patient) + EFG_PLANEPOSPATIENT, + /// Plane Orientation (Patient) + EFG_PLANEORIENTPATIENT, + /// Radiopharmaceutical Usage + EFG_RADIOPHARAMAUSAGE, + /// Real World Value Mapping + EFG_REALWORLDVALUEMAPPING, + /// Respiratory Synchronization + EFG_RESPIRATORYSYNC, + /// Segmentation Macro + EFG_SEGMENTATION, + /// Temporal Position Macro + EFG_TEMPORALPOSITION, + /// Unassigned Shared Converted Attributes Macro + EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES, + /// US Image Description Macro + EFG_USIMAGEDESCRIPTION + }; + + /** Functional group types + */ + enum E_FGSharedType + { + /// Unknown + EFGS_UNKNOWN, + /// Functional Group can be shared or per-frame + EFGS_BOTH, + /// Functional Group can only be shared (not per-frame) + EFGS_ONLYSHARED, + /// Functional Group can only be per-frame (not shared) + EFGS_ONLYPERFRAME + }; + + /** US Image Description Frame Type (first value) + */ + enum E_FGUSFrameType + { + /// Unknown + EFGFT_UNKNOWN, + /// ORIGINAL + EFGFT_ORIGINAL, + /// DERIVED + EFGFT_DERIVED + }; + + // -- static helpers -- + + /** Returns functional group type based on tag key + * @param key The key to get the group type for + * @return The functional group type + */ + static E_FGType tagKey2FGType(const DcmTagKey& key); + + /** Returns the name of the functional group based on the group type + * @param fgType The functional group type + * @return The name of the functional group + */ + static OFString FGType2OFString(const E_FGType fgType); + + /** Returns the name of a functional group based on a given tag key + * @param key The tag key to get the functional group type for + * @return The name of the functional group + */ + static OFString tagKey2FGString(const DcmTagKey& key); }; #endif // FGTYPES_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h b/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h index cfc3fcc1..35b0c587 100644 --- a/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h +++ b/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,161 +23,157 @@ #define FGUSIMAGEDESCRIPTION_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmfg/fgtypes.h" #include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmfg/fgtypes.h" /** Class representing the US Image Description Functional Group */ -class DCMTK_DCMFG_EXPORT FGUSImageDescription: public FGBase +class DCMTK_DCMFG_EXPORT FGUSImageDescription : public FGBase { public: - - /** Constructor, creates empty functional group - */ - FGUSImageDescription(); - - /** Destructor, frees memory - */ - virtual ~FGUSImageDescription(); - - /** Returns a deep copy of this object - * @return Deep copy of this object - */ - virtual FGBase *clone() const; - - /** Clears all data - */ - virtual void clearData(); - - /** Check whether data in this functional group is valid - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check() const; - - /** Read functional group from item, must contain the US Image Description - * Sequence - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem &item); - - /** Write functional group to item, will write to US Image Description - * Sequence - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get shared type of this functional group (can be both, shared and - * per-frame) - * @return Always returns DcmFGTypes::EFGS_BOTH - */ - virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} - - // --- get() functionality --- - - /** Get Frame Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFrameType(OFString& value, - const signed long pos = 0); - - /** Get Volumetric Properties - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetricProperties(OFString& value, - const signed long pos = 0); - - /** Get Volume Based Calculation Technique - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumeBasedCalculationTechnique(OFString& value, - const signed long pos = 0); - - // --- set() functionality --- - - /** Set Frame Type. Frame Type contains up to four values. Value 3 and 4 are - * optional and can be left empty if desired. The values in their order - * of occurrence are: - * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED - * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be - * influenced through this function. - * 3) Image Flavor: Defined Terms listed in the standard - * 4) Derived Pixel Contrast: Defined Terms listed in the standard - * @param pixelDataChar Value 1 of Frame Type - * @param imageFlavor Value 3 of Frame Type - * @param derivedPixelContrast Value 4 of Frame Type - * @param checkValue If OFTrue, the value is checked for conformance. - * @return EC_Normal if setting was successful, error otherwise. - */ - virtual OFCondition setFrameType(const DcmFGTypes::E_FGUSFrameType pixelDataChar, - const OFString& imageFlavor = "", - const OFString& derivedPixelContrast = "", - const OFBool checkValue = OFTrue); - - /** Set Volumetric Properties - * @param value The value to set. Permitted values: - * "VOLUME", "SAMPLED", "DISTORTED", "MIXED" - * @param checkValue If OFTrue, the value is checked for conformance - * @return EC_Normal if setting was successful, error otherwise. - */ - virtual OFCondition setVolumetricProperties(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Volume Based Calculation Technique - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVolumeBasedCalculationTechnique(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * functional groups (this and rhs parameter) are compared by value! - * Both objects (this and rhs) need to have the same type (i.e.\ both - * FGUnknown) to be comparable. This function is used in order - * to decide whether a functional group already exists, or is new. This - * is used in particular to find out whether a given functional group - * can be shared (i.e.\ the same information already exists as shared - * functional group) or is different from the same shared group. In that - * case the shared functional group must be distributed into per-frame - * functional groups, instead. The exact implementation for implementing - * the comparison is not relevant. However, it must be a comparison - * by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the this object, or all compared components match - * but this component is shorter. Also returned if this type and - * rhs type (DcmFGTypes::E_FGType) do not match. - * 1 if either the value of the first component that does not match - * is greater in this object, or all compared components match - * but this component is longer. - */ - virtual int compare(const FGBase& rhs) const; + /** Constructor, creates empty functional group + */ + FGUSImageDescription(); + + /** Destructor, frees memory + */ + virtual ~FGUSImageDescription(); + + /** Returns a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase* clone() const; + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data in this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the US Image Description + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to item, will write to US Image Description + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get shared type of this functional group (can be both, shared and + * per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const + { + return DcmFGTypes::EFGS_BOTH; + } + + // --- get() functionality --- + + /** Get Frame Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFrameType(OFString& value, const signed long pos = 0); + + /** Get Volumetric Properties + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetricProperties(OFString& value, const signed long pos = 0); + + /** Get Volume Based Calculation Technique + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumeBasedCalculationTechnique(OFString& value, const signed long pos = 0); + + // --- set() functionality --- + + /** Set Frame Type. Frame Type contains up to four values. Value 3 and 4 are + * optional and can be left empty if desired. The values in their order + * of occurrence are: + * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED + * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be + * influenced through this function. + * 3) Image Flavor: Defined Terms listed in the standard + * 4) Derived Pixel Contrast: Defined Terms listed in the standard + * @param pixelDataChar Value 1 of Frame Type + * @param imageFlavor Value 3 of Frame Type + * @param derivedPixelContrast Value 4 of Frame Type + * @param checkValue If OFTrue, the value is checked for conformance. + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setFrameType(const DcmFGTypes::E_FGUSFrameType pixelDataChar, + const OFString& imageFlavor = "", + const OFString& derivedPixelContrast = "", + const OFBool checkValue = OFTrue); + + /** Set Volumetric Properties + * @param value The value to set. Permitted values: + * "VOLUME", "SAMPLED", "DISTORTED", "MIXED" + * @param checkValue If OFTrue, the value is checked for conformance + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setVolumetricProperties(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Volume Based Calculation Technique + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeBasedCalculationTechnique(const OFString& value, const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; private: + /* Content of US Image Description Macro */ - /* Content of US Image Description Macro */ - - /// Frame Type (CS, VM 4, Required type 1) - DcmCodeString m_FrameType; + /// Frame Type (CS, VM 4, Required type 1) + DcmCodeString m_FrameType; - /// Volumetric Properties (CS 1, VM 1, Required Type 1) - DcmCodeString m_VolumetricProperties; + /// Volumetric Properties (CS 1, VM 1, Required Type 1) + DcmCodeString m_VolumetricProperties; - /// Volume Based Calculation Technique (CS, VM 1, Required Type 1) - DcmCodeString m_VolumeBasedCalculationTechnique; + /// Volume Based Calculation Technique (CS, VM 1, Required Type 1) + DcmCodeString m_VolumeBasedCalculationTechnique; }; #endif // FGUSIMAGEDESCRIPTION_H - diff --git a/dcmfg/include/dcmtk/dcmfg/stack.h b/dcmfg/include/dcmtk/dcmfg/stack.h index a04b84a2..28956f7e 100644 --- a/dcmfg/include/dcmtk/dcmfg/stack.h +++ b/dcmfg/include/dcmtk/dcmfg/stack.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,10 +23,11 @@ #define FGSTACK_H #include "dcmtk/config/osconfig.h" -#include + +#include "dcmtk/dcmfg/fgdefine.h" #include "dcmtk/ofstd/ofstring.h" #include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/dcmfg/fgdefine.h" +#include /** Class representing a stack in the context of an Enhanced DICOM object. * Therefore the class stores the ID of the stack (Stack ID) and all the frame @@ -36,105 +37,102 @@ class DCMTK_DCMFG_EXPORT FGStack { public: - - // Make sure the main interface class has easy access to internal members - friend class FGStackInterface; - - /// Iterator type for iterating over the frames of a stack - typedef OFMap::iterator iterator; - - /// Const iterator for iterating over the frames of a stack - typedef OFMap::const_iterator const_iterator; - - /** Constructor, creates stack from Stack ID and assigned frame numbers - * @param stackID The Stack ID of the stack - * @param frameNumbers A map with frame numbers as the keys, and the - * position of the frame within the stack as the value for each - * frame. First position is 1. There may be frames having the same - * positions in the same stack. However, in that case the standard - * lists some elements which at least must have the same values, then: - * - Dimension Organization UID (0020,9164) to qualify the Stack ID - * - Image Position (Patient) (0020,0032) - * - Image Orientation (Patient) (0020,0037) - * - Rows (0028,0010) * first value of Pixel Spacing (0028,0030) (= field of view in the row direction) - * - Columns (0028,0011) * second value of Pixel Spacing (0028,0030) (= field of view in the column direction) - * - Slice Thickness (0018,0050) - * The values may change over time (last check was DICOM 2014a), so - * the latest edition of the standard should be consulted if it is - * planned to apply the same in-stack position to different frames. - */ - FGStack(const OFString& stackID, - const OFMap frameNumbers); - - /** Constructor, create empty stack with given Stack ID (and fill in frames - * later) - * @param stackID The Stack ID of the frame - */ - FGStack(const OFString& stackID); - - /** Virtual destructor, frees memory - */ - virtual ~FGStack(); - - /** Return const iterator to first frame (not sorted after stack position) - * @return Const iterator to first frame - */ - const_iterator begin() const; - - /** Return iterator to first frame (not sorted after stack position) - * @return Iterator to first frame - */ - iterator begin(); - - /** Return const iterator pointing behind last frame (not sorted after stack position) - * @return Const iterator pointing behind last frame - */ - const_iterator end() const; - - /** Return iterator pointing behind last frame (not sorted after stack position) - * @return Iterator pointing behind last frame - */ - iterator end(); - - /** Add frame to stack and set its in-stack position. Any old position - * will be overwritten. - * @param frameNumber The frame number that should be added to the stack - * @param inStackPos The position in the stack (starting from 1). More than - * one frame can have the same position in the stack, however there - * are rules (see documentation of constructor and the DICOM - * standard) - */ - virtual OFBool addFrame(const Uint32 frameNumber, - const Uint32 inStackPos); - - /** Get Stack ID uniquely identifying this stack - * @return The Stack ID - */ - virtual OFString getStackID() const; - - /** Get the stack position for a given frame - * @param frameNumber The number of the frame - * @return The stack position for that frame - */ - Uint32 getInStackPos(const Uint32 frameNumber) const; - - /** Get list of frames that are set to a specific In-Stack Position - * @param inStackPos In-Stack Position Number to find frames for - * @param resultFrameNumbers The frame numbers assigned to that stack - * position - */ - void getFramesAtStackPos(const Uint32 inStackPos, - OFVector& resultFrameNumbers); + /// Make sure the main interface class has easy access to internal members + friend class FGStackInterface; + + /// Iterator type for iterating over the frames of a stack + typedef OFMap::iterator iterator; + + /// Const iterator for iterating over the frames of a stack + typedef OFMap::const_iterator const_iterator; + + /** Constructor, creates stack from Stack ID and assigned frame numbers + * @param stackID The Stack ID of the stack + * @param frameNumbers A map with frame numbers as the keys, and the + * position of the frame within the stack as the value for each + * frame. First position is 1. There may be frames having the same + * positions in the same stack. However, in that case the standard + * lists some elements which at least must have the same values, then: + * - Dimension Organization UID (0020,9164) to qualify the Stack ID + * - Image Position (Patient) (0020,0032) + * - Image Orientation (Patient) (0020,0037) + * - Rows (0028,0010) * first value of Pixel Spacing (0028,0030) (= field of view in the row direction) + * - Columns (0028,0011) * second value of Pixel Spacing (0028,0030) (= field of view in the column + * direction) + * - Slice Thickness (0018,0050) + * The values may change over time (last check was DICOM 2014a), so + * the latest edition of the standard should be consulted if it is + * planned to apply the same in-stack position to different frames. + */ + FGStack(const OFString& stackID, const OFMap frameNumbers); + + /** Constructor, create empty stack with given Stack ID (and fill in frames + * later) + * @param stackID The Stack ID of the frame + */ + FGStack(const OFString& stackID); + + /** Virtual destructor, frees memory + */ + virtual ~FGStack(); + + /** Return const iterator to first frame (not sorted after stack position) + * @return Const iterator to first frame + */ + const_iterator begin() const; + + /** Return iterator to first frame (not sorted after stack position) + * @return Iterator to first frame + */ + iterator begin(); + + /** Return const iterator pointing behind last frame (not sorted after stack position) + * @return Const iterator pointing behind last frame + */ + const_iterator end() const; + + /** Return iterator pointing behind last frame (not sorted after stack position) + * @return Iterator pointing behind last frame + */ + iterator end(); + + /** Add frame to stack and set its in-stack position. Any old position + * will be overwritten. + * @param frameNumber The frame number that should be added to the stack + * @param inStackPos The position in the stack (starting from 1). More than + * one frame can have the same position in the stack, however there + * are rules (see documentation of constructor and the DICOM + * standard) + * @return OFTrue if adding was successful, OFFalse otherwise. So far, always + * returns OFTrue. This might change in the future. + */ + virtual OFBool addFrame(const Uint32 frameNumber, const Uint32 inStackPos); + + /** Get Stack ID uniquely identifying this stack + * @return The Stack ID + */ + virtual OFString getStackID() const; + + /** Get the stack position for a given frame + * @param frameNumber The number of the frame + * @return The stack position for that frame + */ + Uint32 getInStackPos(const Uint32 frameNumber) const; + + /** Get list of frames that are set to a specific In-Stack Position + * @param inStackPos In-Stack Position Number to find frames for + * @param resultFrameNumbers The frame numbers assigned to that stack + * position + */ + void getFramesAtStackPos(const Uint32 inStackPos, OFVector& resultFrameNumbers); private: + /// The Stack ID of this frame + OFString m_StackID; - /// The Stack ID of this frame - OFString m_StackID; - - /// Map with frames, key is the frame number, value is the in-stack position. - /// More than one frame can have the same in-stack position - OFMap m_FrameNumbers; - + /// Map with frames, key is the frame number, value is the in-stack position. + /// More than one frame can have the same in-stack position + OFMap m_FrameNumbers; }; #endif // STACKREADER_H diff --git a/dcmfg/include/dcmtk/dcmfg/stackinterface.h b/dcmfg/include/dcmtk/dcmfg/stackinterface.h index 9c929c70..e1329c4b 100644 --- a/dcmfg/include/dcmtk/dcmfg/stackinterface.h +++ b/dcmfg/include/dcmtk/dcmfg/stackinterface.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,51 +23,46 @@ #define STACKINTERFACE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmap.h" -#include "dcmtk/ofstd/ofstring.h" + #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmfg/fginterface.h" #include "dcmtk/dcmfg/stack.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofstring.h" // Forward declaration class FGFrameContent; - /** Class for convenient access of stacks within an Enhanced DICOM object */ class DCMTK_DCMFG_EXPORT FGStackInterface { public: + FGStackInterface(); - FGStackInterface(); - - OFBool checkConsistency(FGInterface* fgContext = NULL); + OFBool checkConsistency(FGInterface* fgContext = NULL); - virtual void clear(); + virtual void clear(); - virtual ~FGStackInterface(); + virtual ~FGStackInterface(); - virtual OFBool addStack(FGStack* stack); + virtual OFBool addStack(FGStack* stack); - virtual OFCondition read(FGInterface& fgSource); + virtual OFCondition read(FGInterface& fgSource); - virtual OFCondition write(FGInterface& fgDestination); + virtual OFCondition write(FGInterface& fgDestination); - size_t numStacks() const; + size_t numStacks() const; protected: + FGFrameContent* ensureFrameContentFG(const Uint32 frameNo, FGInterface& fg); - FGFrameContent* ensureFrameContentFG(const Uint32 frameNo, - FGInterface& fg); - - // Returns number of errors - virtual size_t checkContext(FGStack* stack, - FGInterface* context); + // Returns number of errors + virtual size_t checkContext(FGStack* stack, FGInterface* context); private: - - /// The stacks found - OFMap m_Stacks; + /// The stacks found + OFMap m_Stacks; }; #endif // STACKINTERFACE_H diff --git a/dcmfg/libsrc/CMakeLists.txt b/dcmfg/libsrc/CMakeLists.txt index 6426874d..44f3c374 100644 --- a/dcmfg/libsrc/CMakeLists.txt +++ b/dcmfg/libsrc/CMakeLists.txt @@ -1,7 +1,19 @@ # create library from source files DCMTK_ADD_LIBRARY(dcmfg + concatenationcreator + concatenationloader fg fgbase + fgctacquisitiondetails + fgctacquisitiontype + fgctadditionalxraysource + fgctexposure + fgctgeometry + fgctimageframetype + fgctposition + fgctreconstruction + fgcttabledynamics + fgctxraydetails fgderimg fgfact fgfracon @@ -10,6 +22,7 @@ DCMTK_ADD_LIBRARY(dcmfg fgpixeltransform fgimagedatatype fginterface + fgirradiationeventid fgpixmsr fgparametricmapframetype fgplanor @@ -18,6 +31,7 @@ DCMTK_ADD_LIBRARY(dcmfg fgplanposvol fgrealworldvaluemapping fgseg + fgtemporalposition fgusimagedescription fgtypes stack diff --git a/dcmfg/libsrc/Makefile.dep b/dcmfg/libsrc/Makefile.dep index 78a385a7..0e6319b3 100644 --- a/dcmfg/libsrc/Makefile.dep +++ b/dcmfg/libsrc/Makefile.dep @@ -1,16 +1,26 @@ -fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fg.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ +concatenationcreator.o: concatenationcreator.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../include/dcmtk/dcmfg/fgtypes.h ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ @@ -18,11 +28,12 @@ fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -33,41 +44,35 @@ fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -95,9 +100,6 @@ fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ @@ -112,24 +114,28 @@ fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h -fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgbase.h ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgtypes.h +concatenationloader.o: concatenationloader.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -155,7 +161,6 @@ fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -163,27 +168,44 @@ fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmfg/concatenationloader.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def ../include/dcmtk/dcmfg/fg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -194,11 +216,9 @@ fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -211,9 +231,6 @@ fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ @@ -227,28 +244,10 @@ fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ - ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ - ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h -fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h +fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ @@ -264,6 +263,13 @@ fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -289,22 +295,15 @@ fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../include/dcmtk/dcmfg/fgderimg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -314,9 +313,8 @@ fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ @@ -364,32 +362,28 @@ fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ - ../include/dcmtk/dcmfg/fgdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h -fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -415,30 +409,17 @@ fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgfact.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -447,10 +428,13 @@ fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -461,9 +445,11 @@ fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -493,22 +479,26 @@ fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgderimg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgfracon.h \ - ../include/dcmtk/dcmfg/fgframeanatomy.h \ - ../include/dcmtk/dcmfg/fgframevoilut.h \ - ../include/dcmtk/dcmfg/fgpixeltransform.h \ - ../include/dcmtk/dcmfg/fgimagedatatype.h \ - ../include/dcmtk/dcmfg/fgparametricmapframetype.h \ - ../include/dcmtk/dcmfg/fgpixmsr.h ../include/dcmtk/dcmfg/fgplanor.h \ - ../include/dcmtk/dcmfg/fgplanorvol.h ../include/dcmtk/dcmfg/fgplanpo.h \ - ../include/dcmtk/dcmfg/fgplanposvol.h ../include/dcmtk/dcmfg/fgseg.h \ - ../include/dcmtk/dcmfg/fgusimagedescription.h \ - ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h -fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h +fgctacquisitiondetails.o: fgctacquisitiondetails.cc \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ @@ -519,15 +509,8 @@ fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmfg/fgctacquisitiondetails.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -542,6 +525,7 @@ fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -553,40 +537,38 @@ fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgfracon.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -597,9 +579,11 @@ fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -630,26 +614,26 @@ fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ - ../include/dcmtk/dcmfg/fgdefine.h -fgframeanatomy.o: fgframeanatomy.cc \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctacquisitiontype.o: fgctacquisitiontype.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgframeanatomy.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgctacquisitiontype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -664,6 +648,7 @@ fgframeanatomy.o: fgframeanatomy.cc \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -675,29 +660,32 @@ fgframeanatomy.o: fgframeanatomy.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ @@ -748,16 +736,14 @@ fgframeanatomy.o: fgframeanatomy.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../include/dcmtk/dcmfg/fgdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -fgframevoilut.o: fgframevoilut.cc \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctadditionalxraysource.o: fgctadditionalxraysource.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ @@ -769,15 +755,16 @@ fgframevoilut.o: fgframevoilut.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmfg/fgctadditionalxraysource.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -803,30 +790,16 @@ fgframevoilut.o: fgframevoilut.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgframevoilut.h ../include/dcmtk/dcmfg/fgbase.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -835,9 +808,13 @@ fgframevoilut.o: fgframevoilut.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -848,9 +825,11 @@ fgframevoilut.o: fgframevoilut.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -880,8 +859,14 @@ fgframevoilut.o: fgframevoilut.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h -fgimagedatatype.o: fgimagedatatype.cc \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctexposure.o: fgctexposure.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ @@ -893,15 +878,8 @@ fgimagedatatype.o: fgimagedatatype.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmfg/fgctexposure.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -916,6 +894,7 @@ fgimagedatatype.o: fgimagedatatype.cc \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -927,41 +906,38 @@ fgimagedatatype.o: fgimagedatatype.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgimagedatatype.h ../include/dcmtk/dcmfg/fgbase.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -972,9 +948,11 @@ fgimagedatatype.o: fgimagedatatype.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -1004,31 +982,29 @@ fgimagedatatype.o: fgimagedatatype.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h -fginterface.o: fginterface.cc \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgctgeometry.o: fgctgeometry.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmfg/fgctgeometry.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1041,6 +1017,10 @@ fginterface.o: fginterface.cc \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1051,40 +1031,1668 @@ fginterface.o: fginterface.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctimageframetype.o: fgctimageframetype.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgctimageframetype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctposition.o: fgctposition.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgctposition.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctreconstruction.o: fgctreconstruction.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgctreconstruction.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgcttabledynamics.o: fgcttabledynamics.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgcttabledynamics.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgctxraydetails.o: fgctxraydetails.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgctxraydetails.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgderimg.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h +fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgctacquisitiondetails.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../include/dcmtk/dcmfg/fgctacquisitiontype.h \ + ../include/dcmtk/dcmfg/fgctadditionalxraysource.h \ + ../include/dcmtk/dcmfg/fgctexposure.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmfg/fgctgeometry.h \ + ../include/dcmtk/dcmfg/fgctimageframetype.h \ + ../include/dcmtk/dcmfg/fgctposition.h \ + ../include/dcmtk/dcmfg/fgctreconstruction.h \ + ../include/dcmtk/dcmfg/fgcttabledynamics.h \ + ../include/dcmtk/dcmfg/fgctxraydetails.h \ + ../include/dcmtk/dcmfg/fgderimg.h ../include/dcmtk/dcmfg/fgfact.h \ + ../include/dcmtk/dcmfg/fgfracon.h \ + ../include/dcmtk/dcmfg/fgframeanatomy.h \ + ../include/dcmtk/dcmfg/fgframevoilut.h \ + ../include/dcmtk/dcmfg/fgimagedatatype.h \ + ../include/dcmtk/dcmfg/fgirradiationeventid.h \ + ../include/dcmtk/dcmfg/fgparametricmapframetype.h \ + ../include/dcmtk/dcmfg/fgpixeltransform.h \ + ../include/dcmtk/dcmfg/fgpixmsr.h ../include/dcmtk/dcmfg/fgplanor.h \ + ../include/dcmtk/dcmfg/fgplanorvol.h ../include/dcmtk/dcmfg/fgplanpo.h \ + ../include/dcmtk/dcmfg/fgplanposvol.h \ + ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ + ../include/dcmtk/dcmfg/fgseg.h \ + ../include/dcmtk/dcmfg/fgtemporalposition.h \ + ../include/dcmtk/dcmfg/fgusimagedescription.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgframeanatomy.o: fgframeanatomy.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgframeanatomy.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgframevoilut.o: fgframevoilut.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgframevoilut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgimagedatatype.o: fgimagedatatype.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgimagedatatype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fginterface.o: fginterface.cc \ + ../../config/include/dcmtk/config/osconfig.h ../include/dcmtk/dcmfg/fg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgfact.h \ ../include/dcmtk/dcmfg/fginterface.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgirradiationeventid.o: fgirradiationeventid.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgirradiationeventid.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1095,9 +2703,11 @@ fginterface.o: fginterface.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -1127,9 +2737,13 @@ fginterface.o: fginterface.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \ - ../include/dcmtk/dcmfg/fg.h ../include/dcmtk/dcmfg/fgbase.h \ - ../include/dcmtk/dcmfg/fgfact.h + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h fgparametricmapframetype.o: fgparametricmapframetype.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ @@ -1142,15 +2756,16 @@ fgparametricmapframetype.o: fgparametricmapframetype.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmfg/fgparametricmapframetype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1176,29 +2791,19 @@ fgparametricmapframetype.o: fgparametricmapframetype.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgparametricmapframetype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ @@ -1209,21 +2814,24 @@ fgparametricmapframetype.o: fgparametricmapframetype.cc \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -1253,7 +2861,12 @@ fgparametricmapframetype.o: fgparametricmapframetype.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h fgpixeltransform.o: fgpixeltransform.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ @@ -1266,15 +2879,17 @@ fgpixeltransform.o: fgpixeltransform.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmfg/fgpixeltransform.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1300,60 +2915,52 @@ fgpixeltransform.o: fgpixeltransform.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgpixeltransform.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ @@ -1377,18 +2984,26 @@ fgpixeltransform.o: fgpixeltransform.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h fgpixmsr.o: fgpixmsr.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgpixmsr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgpixmsr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ @@ -1421,31 +3036,147 @@ fgpixmsr.o: fgpixmsr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgfact.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ @@ -1457,11 +3188,13 @@ fgpixmsr.o: fgpixmsr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h \ @@ -1494,31 +3227,33 @@ fgpixmsr.o: fgpixmsr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgplanor.h \ + ../include/dcmtk/dcmfg/fgbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h -fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgplanor.h ../include/dcmtk/dcmfg/fgbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanorvol.o: fgplanorvol.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1533,6 +3268,7 @@ fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -1544,19 +3280,20 @@ fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmfg/fgplanorvol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -1565,8 +3302,6 @@ fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ @@ -1611,37 +3346,30 @@ fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgfact.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h -fgplanorvol.o: fgplanorvol.cc \ - ../../config/include/dcmtk/config/osconfig.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmfg/fgfact.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1668,44 +3396,38 @@ fgplanorvol.o: fgplanorvol.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgplanorvol.h ../include/dcmtk/dcmfg/fgbase.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1716,9 +3438,11 @@ fgplanorvol.o: fgplanorvol.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -1742,30 +3466,41 @@ fgplanorvol.o: fgplanorvol.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h -fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgplanpo.h ../include/dcmtk/dcmfg/fgbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgplanpo.h \ + ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanposvol.o: fgplanposvol.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgplanposvol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1791,7 +3526,6 @@ fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -1799,11 +3533,10 @@ fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -1812,7 +3545,6 @@ fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ @@ -1864,14 +3596,13 @@ fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgfact.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h -fgplanposvol.o: fgplanposvol.cc \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ @@ -1883,15 +3614,16 @@ fgplanposvol.o: fgplanposvol.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1917,30 +3649,17 @@ fgplanposvol.o: fgplanposvol.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgplanposvol.h ../include/dcmtk/dcmfg/fgbase.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -1949,9 +3668,13 @@ fgplanposvol.o: fgplanposvol.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1962,9 +3685,11 @@ fgplanposvol.o: fgplanposvol.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -1994,26 +3719,36 @@ fgplanposvol.o: fgplanposvol.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h -fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ - ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ - ../include/dcmtk/dcmfg/fgbase.h ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgseg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -2039,7 +3774,6 @@ fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -2047,11 +3781,13 @@ fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -2060,11 +3796,8 @@ fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ @@ -2101,7 +3834,6 @@ fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ @@ -2113,26 +3845,26 @@ fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmfg/fgdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgseg.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgtemporalposition.o: fgtemporalposition.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgtemporalposition.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ @@ -2165,7 +3897,6 @@ fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -2173,14 +3904,9 @@ fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -2189,9 +3915,10 @@ fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ @@ -2228,6 +3955,7 @@ fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ @@ -2238,35 +3966,47 @@ fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../include/dcmtk/dcmfg/fgdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h fgtypes.o: fgtypes.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgtypes.h ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -2278,37 +4018,27 @@ fgtypes.o: fgtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ @@ -2359,25 +4089,24 @@ fgtypes.o: fgtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ - ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h fgusimagedescription.o: fgusimagedescription.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ @@ -2390,15 +4119,16 @@ fgusimagedescription.o: fgusimagedescription.cc \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmfg/fgusimagedescription.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -2424,30 +4154,17 @@ fgusimagedescription.o: fgusimagedescription.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fgusimagedescription.h \ - ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -2456,9 +4173,13 @@ fgusimagedescription.o: fgusimagedescription.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -2469,9 +4190,11 @@ fgusimagedescription.o: fgusimagedescription.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -2501,55 +4224,53 @@ fgusimagedescription.o: fgusimagedescription.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h stack.o: stack.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/stack.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../include/dcmtk/dcmfg/stack.h ../include/dcmtk/dcmfg/fgdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../include/dcmtk/dcmfg/fgdefine.h + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h stackinterface.o: stackinterface.cc \ + ../include/dcmtk/dcmfg/stackinterface.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -2561,42 +4282,41 @@ stackinterface.o: stackinterface.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/stackinterface.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -2607,9 +4327,11 @@ stackinterface.o: stackinterface.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -2639,7 +4361,12 @@ stackinterface.o: stackinterface.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmfg/fginterface.h ../include/dcmtk/dcmfg/fgtypes.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fg.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/stack.h \ - ../include/dcmtk/dcmfg/fgfracon.h + ../include/dcmtk/dcmfg/fginterface.h ../include/dcmtk/dcmfg/fg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmfg/stack.h ../include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h diff --git a/dcmfg/libsrc/Makefile.in b/dcmfg/libsrc/Makefile.in index def09187..0cacad30 100644 --- a/dcmfg/libsrc/Makefile.in +++ b/dcmfg/libsrc/Makefile.in @@ -22,12 +22,42 @@ LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include \ LOCALDEFS = -objs = fgderimg.o fgframevoilut.o fgpixmsr.o fgplanpo.o fgseg.o stackinterface.o \ - fgbase.o fgfact.o fgimagedatatype.o fgplanor.o fgplanposvol.o fgtypes.o \ - fg.o fgfracon.o fginterface.o fgplanorvol.o fgrealworldvaluemapping.o \ - fgusimagedescription.o fgparametricmapframetype.o \ - fgpixeltransform.o fgframeanatomy.o stack.o - +objs = concatenationcreator.o \ + concatenationloader.o \ + fg.o \ + fgbase.o \ + fgctacquisitiondetails.o \ + fgctacquisitiontype.o \ + fgctadditionalxraysource.o \ + fgctexposure.o \ + fgctgeometry.o \ + fgctimageframetype.o \ + fgctposition.o \ + fgctreconstruction.o \ + fgcttabledynamics.o \ + fgctxraydetails.o \ + fgderimg.o \ + fgfact.o \ + fgfracon.o \ + fgframeanatomy.o \ + fgframevoilut.o \ + fgpixeltransform.o \ + fgimagedatatype.o \ + fginterface.o \ + fgirradiationeventid.o \ + fgpixmsr.o \ + fgparametricmapframetype.o \ + fgplanor.o \ + fgplanorvol.o \ + fgplanpo.o \ + fgplanposvol.o \ + fgrealworldvaluemapping.o \ + fgseg.o \ + fgtemporalposition.o \ + fgusimagedescription.o \ + fgtypes.o \ + stack.o \ + stackinterface.o library = libdcmfg.$(LIBEXT) diff --git a/dcmfg/libsrc/concatenationcreator.cc b/dcmfg/libsrc/concatenationcreator.cc new file mode 100644 index 00000000..ff581470 --- /dev/null +++ b/dcmfg/libsrc/concatenationcreator.cc @@ -0,0 +1,476 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for creating Concatenations + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofstd.h" + +// Maximum number of instances that make up a Concatenation +const Uint16 ConcatenationCreator::m_MAX_INSTANCES_PER_CONCATENATION = 65535; + +/// Maximum number of bytes for uncompressed pixel data (=2^32-2), derived from +/// 32 bit length field of Pixel Data attribute with even length being required. +Uint32 const ConcatenationCreator::m_MAX_PIXEL_DATA_LENGTH = 4294967294UL; + + +// --------------------------------- Public API ------------------------------ + +// Constructor +ConcatenationCreator::ConcatenationCreator() + : m_configured(OFFalse) + , m_cfgTransferOwnership(OFFalse) + , m_cfgNumFramesPerInstance(25) + , m_numBytesFrame(0) + , m_srcDataset(OFnullptr) + , m_srcSOPInstanceUID() + , m_srcPixelData(OFnullptr) + , m_VRPixelData(EVR_UN) + , m_srcPerFrameFG(OFnullptr) + , m_srcNumFrames(0) + , m_dstNumInstances(0) + , m_dstNumFramesPerInstance(0) + , m_dstNumFramesLastInstance(0) + , m_dstConcatenationUID() + , m_dstInstanceNumber("1") + , m_currentSrcFrame(0) + , m_currentPerFrameItem(OFnullptr) + , m_currentInstanceNum(0) +{ +} + +ConcatenationCreator::~ConcatenationCreator() +{ + if (m_cfgTransferOwnership) + { + delete m_srcDataset; + delete[] m_srcPixelData; + } +} + +OFCondition ConcatenationCreator::setCfgInput(DcmItem* srcDataset, OFBool transferOwnership) +{ + // Check pixel data exists and is in native format (i.e. uncompressed) + DcmElement* elem = NULL; + srcDataset->findAndGetElement(DCM_PixelData, elem); + if (!elem) + return FG_EC_PixelDataMissing; + DcmPixelData* pixDataElem = OFstatic_cast(DcmPixelData*, elem); + if (!pixDataElem) + return FG_EC_PixelDataMissing; + if (!pixDataElem->canWriteXfer(EXS_LittleEndianExplicit, EXS_LittleEndianExplicit /* ignored */)) + return EC_UnsupportedEncoding; + OFCondition result = pixDataElem->getUint8Array(m_srcPixelData); + if (!m_srcPixelData || result.bad()) + return FG_EC_PixelDataMissing; + + m_srcDataset = srcDataset; + + m_cfgTransferOwnership = transferOwnership; + + // All fine + return EC_Normal; +} + +OFCondition ConcatenationCreator::setCfgInput(DcmItem* srcDataset, + Uint8* pixelData, + size_t pixelDataLength, + OFBool transferOwnership) +{ + // Check input parameters + if (!pixelData) + return FG_EC_PixelDataMissing; + + m_srcDataset = srcDataset; + m_srcPixelData = pixelData; + m_cfgTransferOwnership = transferOwnership; + + // All fine + return EC_Normal; +} + +OFCondition ConcatenationCreator::setCfgFramesPerInstance(Uint32 numFramesPerInstance) +{ + m_cfgNumFramesPerInstance = numFramesPerInstance; + return EC_Normal; +} + +OFBool ConcatenationCreator::setCfgInstanceNumber(const OFString& instanceNumber) +{ + if (DcmIntegerString::checkStringValue(instanceNumber, "1").bad()) + return OFFalse; + + m_dstInstanceNumber = instanceNumber; + return OFTrue; +} + +OFCondition ConcatenationCreator::writeNextInstance(DcmItem& dstDataset) +{ + OFCondition result; + if (!m_configured) + { + result = configureCommon(); + if (result.bad()) + { + return result; + } + } + + // Store number of frames for this instance for later use + Uint32 numFramesThisInstance = numFramesCurrentDstInstance(); + if (numFramesThisInstance == 0) + { + return FG_EC_ConcatenationComplete; + } + + // Clone destination dataset from source dataset, + // Remove pixel data and per-frame functional groups before cloning, and re-insert + // it again in order to leave the original dataset in unmodified state + DcmElement* backup1 = m_srcDataset->remove(DCM_PerFrameFunctionalGroupsSequence); + DcmElement* backup2 = m_srcDataset->remove(DCM_PixelData); + dstDataset = *m_srcDataset; + m_srcDataset->insert(backup1); + m_srcDataset->insert(backup2); + + // Allocate element/buffer for destination pixel data and other heap memory + OFunique_ptr dstPixelData(new DcmPixelData(DCM_PixelData)); + OFunique_ptr dstPerFrameSeq(new DcmSequenceOfItems(DCM_PerFrameFunctionalGroupsSequence)); + if (!dstPixelData || !dstPerFrameSeq) + { + return EC_MemoryExhausted; + } + + Uint8* dstData = NULL; + size_t numTotalBytesInstance = m_numBytesFrame * numFramesThisInstance; + // Cast is safe, checked in configureCommon() + dstPixelData->createUint8Array(OFstatic_cast(Uint32, numTotalBytesInstance), dstData); + if (!dstData) + { + return EC_MemoryExhausted; + } + dstPixelData->setVR(m_VRPixelData); + memcpy(dstData, &(m_srcPixelData[m_numBytesFrame * m_currentSrcFrame]), numTotalBytesInstance); + result = dstDataset.insert(dstPixelData.release()); + if (result.good()) + { + // Copy per-frame functional groups for the related frames + for (size_t frameCount = 0; frameCount < numFramesThisInstance; frameCount++) + { + if ((m_currentPerFrameItem == NULL) && (m_currentSrcFrame == m_dstNumInstances - 1)) + { + // Last instance might have less frames + break; + } + else if ((m_currentPerFrameItem == NULL) && (m_currentSrcFrame != m_dstNumInstances - 1)) + { + DCMFG_ERROR("Not enough items in Per-frame Functional group while copying instance #" + << m_currentSrcFrame + 1 << "/" << m_dstNumInstances); + result = FG_EC_NotEnoughFrames; + break; + } + DcmItem* newPerFrameItem = OFstatic_cast(DcmItem*, m_currentPerFrameItem->clone()); + if (newPerFrameItem) + { + dstPerFrameSeq->insert(newPerFrameItem); + } + else + { + result = EC_MemoryExhausted; + break; + } + goToNextFrame(); + } + if (result.good()) + { + result = dstDataset.insert(dstPerFrameSeq.release()); + } + if (result.good()) + { + result = setConcatenationAttributes(dstDataset, numFramesThisInstance); + } + } + if (result.good()) + { + m_currentInstanceNum++; + } + return result; +} + +OFCondition ConcatenationCreator::writeNextInstance(const OFFilename& fn) +{ + OFCondition result; + if (!m_configured) + { + result = configureCommon(); + if (result.bad()) + { + return result; + } + } + DcmFileFormat dcmff; + result = writeNextInstance(*(dcmff.getDataset())); + if (result.good()) + { + result = dcmff.saveFile(fn, EXS_LittleEndianExplicit); + } + return result; +} + +size_t ConcatenationCreator::getNumInstances() +{ + if (!m_configured) + { + OFCondition result = configureCommon(); + if (result.bad()) + { + DCMFG_ERROR("Unable to compute number of instances for Concatenation, maybe input not intialized?)"); + return 0; + } + } + return m_dstNumInstances; +} + +// --------------------------------- Helpers ------------------------------ + +OFBool ConcatenationCreator::checkSOPClass(DcmItem& srcDataset) +{ + // Check whether the SOP Class is not one of the following: + // - Opthalmic Tomography Image Storage + // - Opthalmic Optical Coherence Tomography B-Scan Volume Analysis + // since the standard forbids to make Concatenations of these. + OFString sopClass; + srcDataset.findAndGetOFStringArray(DCM_SOPClassUID, sopClass); + if (sopClass.empty()) + return OFFalse; + + if ((sopClass == UID_OphthalmicTomographyImageStorage) + || (sopClass == UID_OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage)) + return OFFalse; + + return OFTrue; +} + +OFBool ConcatenationCreator::checkColorModel(DcmItem& srcDataset) +{ + OFString str; + srcDataset.findAndGetOFStringArray(DCM_PhotometricInterpretation, str); + if (str.empty()) + { + DCMFG_ERROR("Photometric Interpretation is missing"); + return OFFalse; + } + if ((str != "RGB") && (str != "MONOCHROME1") && (str != "MONOCHROME2") && (str != "YBR_FULL")) + { + DCMFG_ERROR("Photometric Interpretation '" << str << "' not supported"); + return OFFalse; + } + + Uint16 p; + if (srcDataset.findAndGetUint16(DCM_PlanarConfiguration, p).good()) + { + if (p != 0) + { + DCMFG_ERROR("Planar Configuration '" << p << "' not supported (must be 0 if present)"); + return OFFalse; + } + } + + return OFTrue; +} + +OFCondition ConcatenationCreator::setConcatenationAttributes(DcmItem& dstDataset, Uint32 numFramesCurrentInstance) +{ + OFCondition result = dstDataset.putAndInsertOFStringArray(DCM_ConcatenationUID, m_dstConcatenationUID); + if (result.good()) + result = dstDataset.putAndInsertOFStringArray(DCM_InstanceNumber, m_dstInstanceNumber); + if (result.good()) + result = dstDataset.putAndInsertUint32(DCM_ConcatenationFrameOffsetNumber, + m_currentInstanceNum * m_dstNumFramesPerInstance); + if (result.good()) + result = dstDataset.putAndInsertOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, m_srcSOPInstanceUID); + if (result.good()) + result = dstDataset.putAndInsertUint16(DCM_InConcatenationNumber, m_currentInstanceNum + 1 /* first is #1 */); + if (result.good()) + { + // safe cast since configureCommon() already checks whether m_dstNumInstances is in Uint16 range + result = dstDataset.putAndInsertUint16(DCM_InConcatenationTotalNumber, OFstatic_cast(Uint16, m_dstNumInstances)); + } + if (result.good()) + { + + OFStringStream ss; + ss << numFramesCurrentInstance; + result = dstDataset.putAndInsertOFStringArray(DCM_NumberOfFrames, ss.str().c_str()); + } + if (result.good()) + { + char buf[100]; + dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT); + result = dstDataset.putAndInsertOFStringArray(DCM_SOPInstanceUID, buf); + } + return result; +} + +OFCondition ConcatenationCreator::goToNextFrame() +{ + // Check whether converter is initialized, and whether frames are left + if ((m_currentPerFrameItem == NULL) || (m_currentSrcFrame == m_srcNumFrames)) + { + return FG_EC_NotEnoughFrames; + } + else + { + m_currentPerFrameItem = OFstatic_cast(DcmItem*, m_srcPerFrameFG->nextInContainer(m_currentPerFrameItem)); + m_currentSrcFrame++; + } + return EC_Normal; +} + +Uint32 ConcatenationCreator::numFramesCurrentDstInstance() +{ + Uint32 numFrames = 0; + // Calculate last frame number that will be part of "regular" bucket size + Uint32 lastRegular = (m_srcNumFrames / m_dstNumFramesPerInstance) * m_dstNumFramesPerInstance - 1; + if (m_currentSrcFrame == lastRegular + 1) + { + numFrames = m_dstNumFramesLastInstance; + } + else if (m_currentSrcFrame > lastRegular + 1) + { + return 0; + } + else + { + numFrames = m_dstNumFramesPerInstance; + } + return numFrames; +} + +OFCondition ConcatenationCreator::configureCommon() +{ + if (!m_srcDataset || !m_srcPixelData) + return EC_IllegalCall; + + // Check for Shared/Per-Frame Functional Group Sequence + OFCondition result = m_srcDataset->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, m_srcPerFrameFG); + if (result.bad()) + return FG_EC_NoPerFrameFG; + if (!m_srcDataset->tagExists(DCM_SharedFunctionalGroupsSequence)) + return FG_EC_NoSharedFG; + + // Check SOP Class allows Concatenations + if (!checkSOPClass(*m_srcDataset)) + return FG_EC_SOPClassForbidsConcatenations; + + // Check Photometric Interpretation and Planar Configuration + if (!checkColorModel(*m_srcDataset)) + return FG_EC_UnsupportedPixelDataLayout; + + // Check whether number of frames valid in conversion context + m_dstNumFramesPerInstance = m_cfgNumFramesPerInstance; + Sint32 srcNumFrames = 0; + result = m_srcDataset->findAndGetSint32(DCM_NumberOfFrames, srcNumFrames); + if (result.bad() || (srcNumFrames <= 1)) + return FG_EC_NotEnoughFrames; + m_srcNumFrames = OFstatic_cast(Uint32, srcNumFrames); // safe since we checked value before + if (m_srcNumFrames < m_dstNumFramesPerInstance) + return FG_EC_NotEnoughFrames; + + // Remember number of instances to be produced + Uint32 u32 = m_srcNumFrames / m_dstNumFramesPerInstance; + m_dstNumFramesLastInstance = m_srcNumFrames % m_dstNumFramesPerInstance; + if (m_dstNumFramesLastInstance > 0) + { + u32++; + } + if (u32 > m_MAX_INSTANCES_PER_CONCATENATION) + { + DCMFG_ERROR("Too many concatenation instances (" << u32 << "), maximum is " << m_MAX_INSTANCES_PER_CONCATENATION); + return FG_EC_InvalidData; + } + m_dstNumInstances = OFstatic_cast(Uint16, u32); // safe now + + // Check whether pixel data for one instance stays below 4 GB + size_t numTotalBytesInstance = m_numBytesFrame * m_dstNumFramesPerInstance; + if (numTotalBytesInstance > m_MAX_PIXEL_DATA_LENGTH) + { + DCMFG_ERROR("Uncompressed pixel data must not exceed " << m_MAX_PIXEL_DATA_LENGTH << "bytes per concatenation instance"); + return FG_EC_PixelDataDimensionsInvalid; + } + + // Check whether number of items in per-frame functional groups is identical to Number of Frames attribute + if (m_srcNumFrames != m_srcPerFrameFG->card()) + { + DCMFG_ERROR("Number of Frames attribute does not equal number of items in Per-frame Functional Group Sequence"); + return FG_EC_NotEnoughFrames; + } + + // Check pixel data length correct, i.e. whether there is a sufficient amount of data available + Uint16 bitsAlloc, rows, cols; + bitsAlloc = rows = cols = 0; + m_srcDataset->findAndGetUint16(DCM_BitsAllocated, bitsAlloc); + m_srcDataset->findAndGetUint16(DCM_Rows, rows); + m_srcDataset->findAndGetUint16(DCM_Columns, cols); + if ((rows == 0) || (cols == 0)) + return FG_EC_PixelDataDimensionsInvalid; + // 8, 16 bit and 1 bit (relevant for Segmentation objects) are supported + if ((bitsAlloc != 16) && (bitsAlloc != 8) && (bitsAlloc != 1)) + return FG_EC_PixelDataDimensionsInvalid; + if ((bitsAlloc == 1) && (m_dstNumFramesPerInstance % 8 != 0) && (m_dstNumFramesPerInstance * rows * cols % 8 != 0)) + { + DCMFG_ERROR("Can only handle frames per instance (or rows*cols*frames per instance) dividable by 8 for binary " + "segmentations"); + return EC_InvalidValue; + } + m_numBytesFrame = rows * cols * bitsAlloc / 8; + // In case of 1 bit allocated, tiny images might result in 0 bytes + // calculated, so round to 1 byte minimum + if (m_numBytesFrame == 0) + m_numBytesFrame = 1; + if (bitsAlloc <= 8) // 1 or 8 bit + { + m_VRPixelData = EVR_OB; + } + else + { + m_VRPixelData = EVR_OW; + } + // Store source SOP Instance UID + m_srcDataset->findAndGetOFStringArray(DCM_SOPInstanceUID, m_srcSOPInstanceUID); + if (m_srcSOPInstanceUID.empty()) + return EC_InvalidValue; // better code + + // Create Concatenation UID + char buf[65]; + m_dstConcatenationUID = dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT); + + // Set initial context, i.e. initialize for first frame + m_currentPerFrameItem = OFstatic_cast(DcmItem*, m_srcPerFrameFG->nextInContainer(NULL)); + m_currentSrcFrame = 0; + + m_configured = OFTrue; + return result; +} diff --git a/dcmfg/libsrc/concatenationloader.cc b/dcmfg/libsrc/concatenationloader.cc new file mode 100644 index 00000000..3833ddc4 --- /dev/null +++ b/dcmfg/libsrc/concatenationloader.cc @@ -0,0 +1,592 @@ +/* + * + * Copyright (C) 2019-2020, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for loading Concatenations + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmfg/fg.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofstd.h" + +// --------------------------------- Public API ------------------------------ + +// Constructor +ConcatenationLoader::ConcatenationLoader() + : m_Concats() + , m_FailedFiles() + , m_ignoreMissingSourceUID(OFFalse) + , m_Result(NULL) + , m_Frames() +{ +} + +ConcatenationLoader::~ConcatenationLoader() +{ + OFMap::iterator it = m_Concats.begin(); + while (it != m_Concats.end()) + { + delete it->second; + m_Concats.erase(it); + it = m_Concats.begin(); + } +} + +void ConcatenationLoader::setIgnoreMissingSourceUID(const OFBool ignore) +{ + m_ignoreMissingSourceUID = ignore; +} + +OFCondition ConcatenationLoader::scan(const OFFilename& directory, const OFFilename& pattern, OFBool recursive) +{ + OFList files; + size_t results = OFStandard::searchDirectoryRecursively(directory, files, pattern, "", recursive); + DCMFG_DEBUG("Found " << results << " for Concatenation scanning"); + return scan(files); +} + +OFCondition ConcatenationLoader::scan(const OFList& files) +{ + OFCondition result; + OFListConstIterator(OFFilename) it = files.begin(); + size_t count = 1; + while (it != files.end()) + { + DCMFG_DEBUG("Scanning file #" << count << "/" << files.size()); + Info info; + handleFile(*it, info); + it++; + count++; + } + + doScanFinalChecks(); + return result; +} + +OFCondition ConcatenationLoader::doScanFinalChecks() +{ + ScanResultIt c = m_Concats.begin(); + while (c != m_Concats.end()) + { + if ((c->second->m_inConcatTotalNumber > 0) && (c->second->m_Files.size() != (c->second->m_inConcatTotalNumber))) + { + DCMFG_WARN("In-Concatenation Total Number (" + << c->second->m_inConcatTotalNumber << ") does not match number of Instances (" + << c->second->m_Files.size() << ") found for this Concatenation"); + } + c++; + } + return EC_Normal; +} + +void ConcatenationLoader::handleFile(const OFFilename& file, ConcatenationLoader::Info& info) +{ + OFCondition result; + DcmFileFormat dcmff; + OFString err; + Info::Instance inst; + result = dcmff.loadFile(file); + if (result.good()) + { + DcmDataset* dset = dcmff.getDataset(); + if (dset) + { + dset->findAndGetOFStringArray(DCM_SOPInstanceUID, inst.m_sopInstanceUID); + dset->findAndGetOFStringArray(DCM_ConcatenationUID, info.m_ConcatenationUID); + dset->findAndGetOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, info.m_SourceUID); + dset->findAndGetUint16(DCM_InConcatenationTotalNumber, info.m_inConcatTotalNumber); + dset->findAndGetOFStringArray(DCM_PatientID, info.m_PatientID); + dset->findAndGetOFStringArray(DCM_StudyInstanceUID, info.m_StudyInstanceUID); + dset->findAndGetOFStringArray(DCM_SeriesInstanceUID, info.m_SeriesInstanceUID); + dset->findAndGetOFStringArray(DCM_SOPClassUID, info.m_SOPClassUID); + dset->findAndGetUint16(DCM_BitsAllocated, info.m_BitsAlloc); + dset->findAndGetUint16(DCM_Rows, info.m_Rows); + dset->findAndGetUint16(DCM_Columns, info.m_Cols); + Sint32 numFrames = 0; + if (dset->findAndGetSint32(DCM_NumberOfFrames, numFrames).good()) + { + if (numFrames > 0) + inst.m_NumberOfFrames = OFstatic_cast(Uint32, numFrames); + } + dset->findAndGetUint16(DCM_InConcatenationNumber, inst.m_InConcatenationNumber); + inst.m_Filename = file; + checkAndInsertInfo(info, inst, err); + } + else + { + err = "No dataset found"; + } + } + else + { + err = "No DICOM file"; + } + if (!err.empty()) + { + m_FailedFiles.push_back(Failure(file, err, inst.m_sopInstanceUID)); + } +} + +void ConcatenationLoader::checkAndInsertInfo(const ConcatenationLoader::Info& info, + const ConcatenationLoader::Info::Instance& inst, + OFString& error) +{ + if (!info.m_ConcatenationUID.empty()) + { + OFMap::iterator it = m_Concats.find(info.m_ConcatenationUID); + if (it == m_Concats.end()) + { + if ((!info.m_SourceUID.empty() || m_ignoreMissingSourceUID) && (!info.m_StudyInstanceUID.empty()) + && (!info.m_SeriesInstanceUID.empty()) && (!info.m_SOPClassUID.empty()) && (info.m_BitsAlloc != 0) + && (info.m_Rows != 0) && (info.m_Cols != 0) && (inst.m_InConcatenationNumber != 0) + && (!inst.m_sopInstanceUID.empty()) && (inst.m_NumberOfFrames != 0)) + { + // This is a new concatenation, add to list + Info* newInfo = new Info; + *newInfo = info; + newInfo->m_NumTotalFrames = inst.m_NumberOfFrames; + newInfo->m_Files.push_back(inst); + if (!m_Concats.insert(OFMake_pair(info.m_ConcatenationUID, newInfo)).second) + { + error = "Cannot insert into internal data structure"; + delete newInfo; + } + } + else + { + error = "File does not provide all required Concatenation Data"; + } + } + else + { + Info* c = (*it).second; + if ((c->m_BitsAlloc == info.m_BitsAlloc) && (c->m_Cols == info.m_Cols) && (c->m_Rows == info.m_Rows) + && (c->m_SOPClassUID == info.m_SOPClassUID) && (c->m_SeriesInstanceUID == info.m_SeriesInstanceUID) + && (c->m_StudyInstanceUID == info.m_StudyInstanceUID) && emptyOrEqual(c->m_PatientID, info.m_PatientID) + && emptyOrEqual(c->m_SourceUID, info.m_SourceUID) + && zeroOrEqual(c->m_inConcatTotalNumber, info.m_inConcatTotalNumber) + && (c->m_ConcatenationUID == info.m_ConcatenationUID)) /* should always be true, but... */ + { + // Add file to this concatenation + OFListIterator(ConcatenationLoader::Info::Instance) sortIt = c->m_Files.begin(); + while (sortIt != c->m_Files.end()) + { + if ((*sortIt).m_InConcatenationNumber > inst.m_InConcatenationNumber) + break; + sortIt++; + } + c->m_NumTotalFrames += inst.m_NumberOfFrames; + c->m_inConcatTotalNumber = getNotZero(c->m_inConcatTotalNumber, info.m_inConcatTotalNumber); + c->m_Files.insert(sortIt, inst); + } + else + { + error = "Concatenation Data inconsistent to rest of Concatenation"; + } + } + } + else + { + error = "File is not part of Concatenation"; + } +} + +const ConcatenationLoader::TScanResult& ConcatenationLoader::getInfo() +{ + return m_Concats; +} + +const ConcatenationLoader::TScanFailures& ConcatenationLoader::getFailedFiles() +{ + return m_FailedFiles; +} + +OFCondition +ConcatenationLoader::load(const OFString& concatenationUID, DcmDataset* dataset, OFVector& frames) +{ + if (dataset == NULL) + return EC_IllegalParameter; + m_Result = dataset; + + OFCondition result; + ScanResultIt concat = m_Concats.find(concatenationUID); + if (concat != m_Concats.end()) + { + Info* c = concat->second; + if (c || !c->m_Files.empty()) + { + // Create dataset to work with from first concatenation instance + DCMFG_DEBUG("Loading Concatenation " << concatenationUID << " from " << c->m_Files.size() << " instances"); + result = prepareTemplate(*concat->second); + if (result.good()) + { + OFListIterator(ConcatenationLoader::Info::Instance) inst = c->m_Files.begin(); + inst++; // first instance already handled + while (result.good() && (inst != c->m_Files.end())) + { + DcmFileFormat dcmff; + result = dcmff.loadFile(inst->m_Filename); + if (result.good()) + { + if ((*c).m_BitsAlloc == 1) + { + result = extractBinaryFrames(*dcmff.getDataset(), *c, inst->m_NumberOfFrames); + } + else + { + result = extractFrames(*dcmff.getDataset(), *c, inst->m_NumberOfFrames); + } + + if (result.good()) + result = movePerFrameItems(*dcmff.getDataset()); + } + inst++; + } + if (result.good()) + { + if (result.good()) + { + frames = m_Frames; + result = insertDestinationAttributes(); + } + else + { + DcmIODUtil::freeContainer(m_Frames); + } + } + } + } + else + { + result = EC_InternalError; + } + } + + return result; +} + +OFCondition ConcatenationLoader::prepareTemplate(ConcatenationLoader::Info& firstInstance) +{ + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(firstInstance.m_Files.front().m_Filename); + if (result.good()) + { + *m_Result = *dcmff.getDataset(); + OFString srcUID; + result = m_Result->findAndGetOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, srcUID); + if (result.bad() && m_ignoreMissingSourceUID) + result = EC_Normal; + if (result.good()) + result = deleteConcatAttributes(*m_Result); + if (result.good()) + result = m_Result->putAndInsertOFStringArray(DCM_SOPInstanceUID, srcUID); + if (result.good()) + { + result = extractFrames(*m_Result, firstInstance, firstInstance.m_Files.front().m_NumberOfFrames); + m_Result->findAndDeleteElement(DCM_PixelData); + } + } + return result; +} + +OFCondition ConcatenationLoader::deleteConcatAttributes(DcmItem& item) +{ + item.findAndDeleteElement(DCM_ConcatenationUID); + item.findAndDeleteElement(DCM_InConcatenationNumber); + item.findAndDeleteElement(DCM_InConcatenationTotalNumber); + item.findAndDeleteElement(DCM_SOPInstanceUIDOfConcatenationSource); + item.findAndDeleteElement(DCM_ConcatenationFrameOffsetNumber); + item.findAndDeleteElement(DCM_NumberOfFrames); + item.findAndDeleteElement(DCM_ContentDate); + item.findAndDeleteElement(DCM_ContentTime); + item.findAndDeleteElement(DCM_SOPInstanceUID); + return EC_Normal; +} + +OFCondition ConcatenationLoader::extractFrames(DcmItem& item, Info& info, const Uint32 numFrames) +{ + const Uint8* pixData = NULL; + OFCondition result = item.findAndGetUint8Array(DCM_PixelData, pixData); + if (result.good() && pixData) + { + size_t bytes_per_frame = 0; + result = computeBytesPerFrame(info.m_Rows, info.m_Cols, info.m_BitsAlloc, bytes_per_frame); + if (result.good()) + { + const Uint8* ptr = pixData; + for (Uint32 f = 0; f < numFrames; f++) + { + DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); + if (frame) + { + frame->length = bytes_per_frame; + frame->pixData = new Uint8[frame->length]; + if (frame->pixData) + { + memcpy(frame->pixData, ptr, frame->length); + ptr += frame->length; + m_Frames.push_back(frame); + } + else + { + result = EC_MemoryExhausted; + } + } + else + { + result = EC_MemoryExhausted; + } + } + } + } + else + { + result = FG_EC_PixelDataMissing; + } + return result; +} + +OFCondition ConcatenationLoader::extractBinaryFrames(DcmItem& item, Info& info, const Uint32 numFrames) +{ + Uint8* pixData = NULL; + DcmElement* pixDataElem = NULL; + OFCondition result = item.findAndGetElement(DCM_PixelData, pixDataElem); + if (result.good()) + result = pixDataElem->getUint8Array(pixData); + if (result.good() && pixData) + { + result = DcmIODUtil::extractBinaryFrames(pixData, numFrames, info.m_Rows * info.m_Cols, m_Frames); + } + else + { + result = FG_EC_PixelDataMissing; + } + return result; +} + +OFCondition ConcatenationLoader::computeBytesPerFrame(const Uint16 rows, + const Uint16 cols, + const Uint16 bitsAlloc, + size_t& bytes_per_frame) +{ + // Usually bytes of one frame simply computes using cols * rows * num bytes per pixel. + // This is only different if bits allocated equals 1, which can happen + // for binary segmentations or black and white secondary capture objects + // (second SC generation). + // Other values than Bits Allocated 16 or 8 are not supported. + bytes_per_frame = bitsAlloc * cols * rows; + if ((bitsAlloc == 16) || (bitsAlloc == 8)) + { + // result in rows * cols * bytes per frame + bytes_per_frame = bytes_per_frame / 8; + } + else if (bitsAlloc == 1) + { + // results in rows * cols / 8 if rows*cols is dividable by 8, + // otherwise rows * cols / 8 +1 (extra byte) + OFBool remainder = (bytes_per_frame % 8 != 0) ? OFTrue: OFFalse; + bytes_per_frame = bytes_per_frame / 8; + if (remainder) + { + bytes_per_frame++; + } + } + else + { + DCMFG_ERROR("Bits Allocated=" << bitsAlloc << " not supported, must be 1, 8 or 16"); + return FG_EC_UnsupportedPixelDataLayout; + } + return EC_Normal; +} + +OFCondition ConcatenationLoader::movePerFrameItems(DcmItem& item) +{ + OFCondition result; + DcmSequenceOfItems* srcPerFrame = NULL; + DcmSequenceOfItems* dstPerFrame = NULL; + m_Result->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, dstPerFrame); + if (item.findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, srcPerFrame).good() && dstPerFrame) + { + while (result.good() && (srcPerFrame->card() != 0)) + { + result = dstPerFrame->append(srcPerFrame->remove(OFstatic_cast(unsigned long, 0))); + } + } + return result; +} + +OFCondition ConcatenationLoader::insertDestinationAttributes() +{ + Info* info = m_Concats.begin()->second; + OFString uid = info->m_SourceUID; + if (uid.empty()) + { + char buf[100]; + dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT); + uid = buf; + DCMFG_WARN("SOP Instance UID of Concatentation Source (0020,0242)​ not set, created new SOP Instance UID " + << uid); + } + OFCondition result = m_Result->putAndInsertOFStringArray(DCM_SOPInstanceUID, uid); + if (result.good()) + { + OFStringStream s; + s << info->m_NumTotalFrames; + result = m_Result->putAndInsertOFStringArray(DCM_NumberOfFrames, s.str().c_str()); + } + if (result.good()) + { + OFDate date; + date.setCurrentDate(); + OFString tempstr; + date.getISOFormattedDate(tempstr, OFFalse /* no delimiters */); + result = m_Result->putAndInsertOFStringArray(DCM_ContentDate, tempstr); + if (result.good()) + { + OFTime time; + time.setCurrentTime(); + time.getISOFormattedTime(tempstr, OFTrue /* include seconds */, OFFalse, OFFalse, OFFalse); + result = m_Result->putAndInsertOFStringArray(DCM_ContentTime, tempstr); + } + } + return result; +} + +OFBool ConcatenationLoader::zeroOrEqual(const size_t num1, const size_t num2) +{ + if (num1 == num2) + return OFTrue; + if ((num1 == 0) || (num2 == 0)) + return OFTrue; + return OFFalse; +} + +OFBool ConcatenationLoader::emptyOrEqual(const OFString& str1, const OFString& str2) +{ + if (str1 == str2) + return OFTrue; + if (str1.empty() || str2.empty()) + return OFTrue; + return OFFalse; +} + +template +T ConcatenationLoader::getNotZero(const T num1, const T num2) +{ + if (num1 != 0) + return num1; + return num2; +} + +ConcatenationLoader::Info::Info() + : m_Files() + , m_FileConatenationSource() + , m_ConcatenationUID() + , m_SourceUID() + , m_inConcatTotalNumber(0) + , m_NumTotalFrames(0) + , m_PatientID() + , m_StudyInstanceUID() + , m_SeriesInstanceUID() + , m_SOPClassUID() + , m_BitsAlloc(0) + , m_Rows(0) + , m_Cols(0) +{ +} + +ConcatenationLoader::Info& ConcatenationLoader::Info::operator=(const ConcatenationLoader::Info& rhs) +{ + this->m_FileConatenationSource = rhs.m_FileConatenationSource; + this->m_ConcatenationUID = rhs.m_ConcatenationUID; + this->m_SourceUID = rhs.m_SourceUID; + this->m_NumTotalFrames = rhs.m_NumTotalFrames; + this->m_inConcatTotalNumber = rhs.m_inConcatTotalNumber; + this->m_PatientID = rhs.m_PatientID; + this->m_StudyInstanceUID = rhs.m_StudyInstanceUID; + this->m_SeriesInstanceUID = rhs.m_SeriesInstanceUID; + this->m_SOPClassUID = rhs.m_SOPClassUID; + this->m_BitsAlloc = rhs.m_BitsAlloc; + this->m_Rows = rhs.m_Rows; + this->m_Cols = rhs.m_Cols; + OFListConstIterator(Instance) it = rhs.m_Files.begin(); + while (it != rhs.m_Files.end()) + { + this->m_Files.push_back(*it); + it++; + } + return *this; +} + +ConcatenationLoader::Info::Info(const ConcatenationLoader::Info& rhs) +{ + if (&rhs == this) + return; + + *this = rhs; +} + +void ConcatenationLoader::Info::print(OFStringStream& out) +{ + out << "Concatenation UID* : " << m_ConcatenationUID << OFendl; + out << " SOP Class UID* : " << m_SOPClassUID << OFendl; + out << " Concatentation Source UID* : " << m_SourceUID << OFendl; + out << " Concatentation Source File : " << m_FileConatenationSource << OFendl; + out << " Number of Frames (computed): " << m_NumTotalFrames << OFendl; + out << " In-conc. Total Number : " << m_inConcatTotalNumber << OFendl; + out << " Patient ID : " << m_PatientID << OFendl; + out << " Study Instance UID* : " << m_StudyInstanceUID << OFendl; + out << " Series Instance UID* : " << m_SeriesInstanceUID << OFendl; + out << " Bits Allocated* : " << m_BitsAlloc << OFendl; + out << " Rows* : " << m_Rows << OFendl; + out << " Columns* : " << m_Cols << OFendl; + out << " Files: " << OFendl; + OFListIterator(Instance) f = m_Files.begin(); + size_t count = 1; + while (f != m_Files.end()) + { + out << " " << count << ". " << (*f).m_Filename << OFendl; + out << " SOP Instance UID: " << (*f).m_sopInstanceUID << OFendl; + out << " Number of Frames: " << (*f).m_NumberOfFrames << OFendl; + out << " In-Concatenation Frame Offset Number: " << (*f).m_InConcatenationNumber << OFendl; + f++; + count++; + } +} + +ConcatenationLoader::Info::~Info() +{ +} + +ConcatenationLoader::Info::Instance::Instance() + : m_Filename() + , m_sopInstanceUID() + , m_NumberOfFrames(0) + , m_InConcatenationNumber(0) +{ +} + +ConcatenationLoader::Info::Instance::~Instance() +{ +} diff --git a/dcmfg/libsrc/fg.cc b/dcmfg/libsrc/fg.cc index b97d2f19..401a1f23 100644 --- a/dcmfg/libsrc/fg.cc +++ b/dcmfg/libsrc/fg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,113 +20,101 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fg.h" +#include "dcmtk/dcmfg/fg.h" FunctionalGroups::FunctionalGroups() -: m_groups() + : m_groups() { } - FunctionalGroups::~FunctionalGroups() { - clear(); + clear(); } - void FunctionalGroups::clear() { - // free memory of underlying map - while ( m_groups.size() > 0) - { - FunctionalGroups::iterator it = m_groups.begin(); - FGBase* fg = (*it).second; - m_groups.erase(it); - delete fg; - } + // free memory of underlying map + while (m_groups.size() > 0) + { + FunctionalGroups::iterator it = m_groups.begin(); + FGBase* fg = (*it).second; + m_groups.erase(it); + delete fg; + } } - - FGBase* FunctionalGroups::find(const DcmFGTypes::E_FGType fgType) { - FGBase* group = NULL; - FunctionalGroups::iterator it = m_groups.find(fgType); - FunctionalGroups::iterator done = m_groups.end(); - if ( it != done) - { - group = (*it).second; - } - return group; + FGBase* group = NULL; + FunctionalGroups::iterator it = m_groups.find(fgType); + FunctionalGroups::iterator done = m_groups.end(); + if (it != done) + { + group = (*it).second; + } + return group; } - FunctionalGroups::iterator FunctionalGroups::begin() { - return m_groups.begin(); + return m_groups.begin(); } - FunctionalGroups::iterator FunctionalGroups::end() { - return m_groups.end(); + return m_groups.end(); } - FunctionalGroups::const_iterator FunctionalGroups::begin() const { - return m_groups.begin(); + return m_groups.begin(); } - FunctionalGroups::const_iterator FunctionalGroups::end() const { - return m_groups.end(); + return m_groups.end(); } - -OFCondition FunctionalGroups::insert(FGBase* group, - const OFBool replaceOld) +OFCondition FunctionalGroups::insert(FGBase* group, const OFBool replaceOld) { - if (group == NULL) - return EC_IllegalParameter; + if (group == NULL) + return EC_IllegalParameter; - OFCondition result; - FGBase* existing = find(group->getType()); - if (existing) - { - if (replaceOld) - { - DCMFG_DEBUG("Replacing existing functional group"); - delete remove(group->getType()); - } - else - { - DCMFG_ERROR("Cannot insert functional group: Group does already exist"); - result = FG_EC_DoubledFG; - } - } - if (result.good()) - { - if ( (m_groups.insert(OFMake_pair(group->getType(), group)).second) ) + OFCondition result; + FGBase* existing = find(group->getType()); + if (existing) { - DCMFG_DEBUG("Functional group successfully inserted: " << DcmFGTypes::FGType2OFString(group->getType())); + if (replaceOld) + { + DCMFG_DEBUG("Replacing existing functional group"); + delete remove(group->getType()); + } + else + { + DCMFG_ERROR("Cannot insert functional group: Group does already exist"); + result = FG_EC_DoubledFG; + } } - else + if (result.good()) { - DCMFG_ERROR("Cannot insert functional group: Internal error"); - result = FG_EC_CouldNotInsertFG; + if ((m_groups.insert(OFMake_pair(group->getType(), group)).second)) + { + DCMFG_DEBUG("Functional group successfully inserted: " << DcmFGTypes::FGType2OFString(group->getType())); + } + else + { + DCMFG_ERROR("Cannot insert functional group: Internal error"); + result = FG_EC_CouldNotInsertFG; + } } - } - return result; + return result; } - FGBase* FunctionalGroups::remove(const DcmFGTypes::E_FGType fgType) { - FGBase* fg = find(fgType); - m_groups.erase(fgType); - return fg; + FGBase* fg = find(fgType); + m_groups.erase(fgType); + return fg; } - diff --git a/dcmfg/libsrc/fgbase.cc b/dcmfg/libsrc/fgbase.cc index d382e054..e2e47b46 100644 --- a/dcmfg/libsrc/fgbase.cc +++ b/dcmfg/libsrc/fgbase.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,220 +20,224 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgbase.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgbase.h" #include "dcmtk/dcmiod/iodcommn.h" // for static element helpers - -FGBase::FGBase(const DcmFGTypes::E_FGType fgType) : - m_fgType(fgType) +FGBase::FGBase(const DcmFGTypes::E_FGType fgType) + : m_fgType(fgType) { } - FGBase::~FGBase() { } - void FGBase::clearData() { } - DcmFGTypes::E_FGType FGBase::getType() const { - return m_fgType; + return m_fgType; } - DcmFGTypes::E_FGSharedType FGBase::getSharedType() const { - return DcmFGTypes::EFGS_UNKNOWN; + return DcmFGTypes::EFGS_UNKNOWN; } - int FGBase::compare(const FGBase& rhs) const { - // Check for equality from FGBase' point of view + // Check for equality from FGBase' point of view - // Same objects? - if (this == &rhs) - return 0; + // Same objects? + if (this == &rhs) + return 0; - // Type identical? - if ( this->getType() != rhs.getType() ) - return -1; + // Type identical? + if (this->getType() != rhs.getType()) + return -1; - // This is all we can do - return 0; + // This is all we can do + return 0; } - OFCondition FGBase::getItemFromFGSequence(DcmItem& source, const DcmTagKey& seqKey, const long unsigned int itemNum, DcmItem*& result) { - result = NULL; - DcmSequenceOfItems *seq = NULL; - if (source.findAndGetSequence(seqKey, seq).bad()) - { - DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) << ")"); - return EC_TagNotFound; - } - result = seq->getItem(itemNum); - if (result == NULL) - { - DCMFG_DEBUG("Functional Group Sequence " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) << ") does not have " << itemNum-1 << " items"); - return FG_EC_NotEnoughItems; - } - return EC_Normal; + result = NULL; + DcmSequenceOfItems* seq = NULL; + if (source.findAndGetSequence(seqKey, seq).bad()) + { + DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) + << ")"); + return EC_TagNotFound; + } + result = seq->getItem(itemNum); + if (result == NULL) + { + DCMFG_DEBUG("Functional Group Sequence " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) + << ") does not have " << itemNum - 1 << " items"); + return FG_EC_NotEnoughItems; + } + return EC_Normal; } +OFCondition FGBase::getNumItemsFromFGSequence(DcmItem& source, const DcmTagKey& seqKey, unsigned long& result) +{ + result = 0; + DcmSequenceOfItems* seq = NULL; + if (source.findAndGetSequence(seqKey, seq).bad()) + { + DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) + << ")"); + return EC_TagNotFound; + } + result = seq->card(); + return EC_Normal; +} OFCondition FGBase::createNewFGSequence(DcmItem& destination, const DcmTagKey& seqKey, - const long unsigned int numItems, + const unsigned long numItems, DcmItem*& firstItem) { - firstItem = NULL; - OFCondition result = destination.insertEmptyElement(seqKey, OFTrue /* replace old */); - if (result.bad()) - { - DCMFG_ERROR("Could not create Functional Group with sequence " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) << ")"); - return FG_EC_CouldNotInsertFG; - } - DcmItem* dummy =NULL; - result = destination.findOrCreateSequenceItem(seqKey, dummy, numItems ); - if (result.bad()) - { - // clean up - destination.findAndDeleteElement(seqKey); - DCMFG_ERROR("Could not create " << numItems << " items in Functional Group with sequence " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) << ")"); - return FG_EC_CouldNotInsertFG; - } - destination.findOrCreateSequenceItem(seqKey, firstItem, 0); - return EC_Normal; -} + if (numItems > OFstatic_cast(unsigned long, OFnumeric_limits::max())) + return EC_IllegalParameter; + firstItem = NULL; + OFCondition result = destination.insertEmptyElement(seqKey, OFTrue /* replace old */); + if (result.bad()) + { + DCMFG_ERROR("Could not create Functional Group with sequence " << seqKey << " (" + << DcmFGTypes::tagKey2FGType(seqKey) << ")"); + return FG_EC_CouldNotInsertFG; + } + DcmItem* dummy = NULL; + result = destination.findOrCreateSequenceItem(seqKey, dummy, OFstatic_cast(signed long, numItems)); + if (result.bad()) + { + // clean up + destination.findAndDeleteElement(seqKey); + DCMFG_ERROR("Could not create " << numItems << " items in Functional Group with sequence " << seqKey << " (" + << DcmFGTypes::tagKey2FGType(seqKey) << ")"); + return FG_EC_CouldNotInsertFG; + } + destination.findOrCreateSequenceItem(seqKey, firstItem, 0); + return EC_Normal; +} // ------------------ class FGUnknown ------------------------------------ - -FGUnknown::FGUnknown(const DcmTagKey& seqStartTag, - const DcmFGTypes::E_FGSharedType sharedType) : - FGBase(DcmFGTypes::EFG_UNKNOWN), - m_seqStartTag(seqStartTag), - m_fgSequence(NULL), - m_sharedType(sharedType) +FGUnknown::FGUnknown(const DcmTagKey& seqStartTag, const DcmFGTypes::E_FGSharedType sharedType) + : FGBase(DcmFGTypes::EFG_UNKNOWN) + , m_seqStartTag(seqStartTag) + , m_fgSequence(NULL) + , m_sharedType(sharedType) { } -FGUnknown::FGUnknown(const FGUnknown& rhs) : - FGBase(DcmFGTypes::EFG_UNKNOWN), - m_seqStartTag(rhs.m_seqStartTag), - m_fgSequence(OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone())), - m_sharedType(rhs.m_sharedType) +FGUnknown::FGUnknown(const FGUnknown& rhs) + : FGBase(DcmFGTypes::EFG_UNKNOWN) + , m_seqStartTag(rhs.m_seqStartTag) + , m_fgSequence(OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone())) + , m_sharedType(rhs.m_sharedType) { } - -FGUnknown & FGUnknown::operator=(const FGUnknown& rhs) +FGUnknown& FGUnknown::operator=(const FGUnknown& rhs) { m_seqStartTag = rhs.m_seqStartTag; - m_fgSequence = OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone()); - m_sharedType = rhs.m_sharedType; + m_fgSequence = OFstatic_cast(DcmSequenceOfItems*, rhs.m_fgSequence->clone()); + m_sharedType = rhs.m_sharedType; return *this; } - void FGUnknown::clearData() { - if (m_fgSequence != NULL) - { - delete m_fgSequence; - m_fgSequence = NULL; - } + if (m_fgSequence != NULL) + { + delete m_fgSequence; + m_fgSequence = NULL; + } } - OFCondition FGUnknown::read(DcmItem& item) { - // clear old data - clearData(); - OFCondition result = item.findAndGetSequence(m_seqStartTag, m_fgSequence, OFFalse /* no depth search */, OFTrue /* create copy! */); - if ( result.bad() ) - { - if (m_fgSequence != NULL) - delete m_fgSequence; - m_fgSequence = NULL; - } - return result; + // clear old data + clearData(); + OFCondition result = item.findAndGetSequence( + m_seqStartTag, m_fgSequence, OFFalse /* no depth search */, OFTrue /* create copy! */); + if (result.bad()) + { + if (m_fgSequence != NULL) + delete m_fgSequence; + m_fgSequence = NULL; + } + return result; } - OFCondition FGUnknown::write(DcmItem& item) { - return item.insert(new DcmSequenceOfItems(*m_fgSequence), OFTrue /* replace old! */); + return item.insert(new DcmSequenceOfItems(*m_fgSequence), OFTrue /* replace old! */); } - OFCondition FGUnknown::check() const { - return EC_Normal; + return EC_Normal; } - int FGUnknown::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result == 0) - { - const FGUnknown* myRhs = OFstatic_cast(const FGUnknown*, &rhs); - - // Compare all elements - if (m_seqStartTag == myRhs->m_seqStartTag) + int result = FGBase::compare(rhs); + if (result == 0) { - if (m_fgSequence && myRhs->m_fgSequence) - { - result = m_fgSequence->compare( *(myRhs->m_fgSequence) ); - } - else if (!m_fgSequence && !myRhs->m_fgSequence) // if both are not set, objects are still equal - { - result = 0; - } - else if (m_fgSequence) - { - result = 1; // this object is bigger (more information) - } - else if (myRhs->m_fgSequence) - { - result = -1; // rhs object is bigger (more information) - } + const FGUnknown* myRhs = OFstatic_cast(const FGUnknown*, &rhs); + + // Compare all elements + if (m_seqStartTag == myRhs->m_seqStartTag) + { + if (m_fgSequence && myRhs->m_fgSequence) + { + result = m_fgSequence->compare(*(myRhs->m_fgSequence)); + } + else if (!m_fgSequence && !myRhs->m_fgSequence) // if both are not set, objects are still equal + { + result = 0; + } + else if (m_fgSequence) + { + result = 1; // this object is bigger (more information) + } + else if (myRhs->m_fgSequence) + { + result = -1; // rhs object is bigger (more information) + } + } + else + { + result = (m_seqStartTag < myRhs->m_seqStartTag) ? -1 : 1; + } } - else - { - result = (m_seqStartTag < myRhs->m_seqStartTag) ? -1 : 1; - } - } - return result; + return result; } - FGUnknown::~FGUnknown() { - clearData(); + clearData(); } - FGBase* FGUnknown::clone() const { - FGUnknown* copy = new FGUnknown(this->m_seqStartTag); - if (copy) - { - *(copy->m_fgSequence) = *(this->m_fgSequence); - } - return copy; + FGUnknown* copy = new FGUnknown(this->m_seqStartTag); + if (copy) + { + *(copy->m_fgSequence) = *(this->m_fgSequence); + } + return copy; } diff --git a/dcmfg/libsrc/fgctacquisitiondetails.cc b/dcmfg/libsrc/fgctacquisitiondetails.cc new file mode 100644 index 00000000..22f5253c --- /dev/null +++ b/dcmfg/libsrc/fgctacquisitiondetails.cc @@ -0,0 +1,398 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Acquisition Details Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctacquisitiondetails.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTAcquisitionDetails::FGCTAcquisitionDetails() + : FGBase(DcmFGTypes::EFG_CTACQUISITIONDETAILS) + , m_Items() +{ +} + +FGCTAcquisitionDetails::~FGCTAcquisitionDetails() +{ + clearData(); +} + +FGBase* FGCTAcquisitionDetails::clone() const +{ + OFunique_ptr copy(new FGCTAcquisitionDetails()); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +void FGCTAcquisitionDetails::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +OFCondition FGCTAcquisitionDetails::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Acquisition Details Sequence from given item +OFCondition FGCTAcquisitionDetails::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTAcquisitionDetailsSequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTAcquisitionDetailsSequence, num, seqItem).good()) + { + FGCTAcquisitionDetailsItem* newItem = new FGCTAcquisitionDetailsItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +/// Write CT Acquisition Detail Sequence into given item +OFCondition FGCTAcquisitionDetails::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence( + result, DCM_CTAcquisitionDetailsSequence, m_Items, item, "1-n", "2", "CTAcquisitionDetailsMacro"); + } + + return result; +} + +int FGCTAcquisitionDetails::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + FGCTAcquisitionDetails* myRhs + = OFconst_cast(FGCTAcquisitionDetails*, (OFstatic_cast(const FGCTAcquisitionDetails*, &rhs))); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(this->m_Items, myRhs->m_Items); +} + +OFVector& FGCTAcquisitionDetails::getCTAcquisitionDetailsItems() +{ + return m_Items; +} + +// ------------ Class FGCTAcquisitionDetailsItem::FGCTAcquisitionDetailsItem ------------- + +FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::FGCTAcquisitionDetailsItem() + : m_ReferencedPathIndex(DCM_ReferencedPathIndex) + , m_RotationDirection(DCM_RotationDirection) + , m_RevolutionTime(DCM_RevolutionTime) + , m_SingleCollimationWidth(DCM_SingleCollimationWidth) + , m_TotalCollimationWidth(DCM_TotalCollimationWidth) + , m_TableHeight(DCM_TableHeight) + , m_GantryDetectorTilt(DCM_GantryDetectorTilt) + , m_DataCollectionDiameter(DCM_DataCollectionDiameter) +{ +} + +FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::~FGCTAcquisitionDetailsItem() +{ + // Nothing to do +} + +// --- get() functionality --- + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +void FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::clearData() +{ + m_DataCollectionDiameter.clear(); + m_GantryDetectorTilt.clear(); + m_ReferencedPathIndex.clear(); + m_RevolutionTime.clear(); + m_RotationDirection.clear(); + m_SingleCollimationWidth.clear(); + m_TableHeight.clear(); + m_TotalCollimationWidth.clear(); +} + +int FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::compare( + const FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem& rhs) const +{ + FGCTAcquisitionDetailsItem* myRhs = OFconst_cast(FGCTAcquisitionDetailsItem*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + int result = m_DataCollectionDiameter.compare(myRhs->m_DataCollectionDiameter); + if (result == 0) + result = m_GantryDetectorTilt.compare(myRhs->m_GantryDetectorTilt); + if (result == 0) + result = m_ReferencedPathIndex.compare(myRhs->m_ReferencedPathIndex); + if (result == 0) + result = m_RevolutionTime.compare(myRhs->m_RevolutionTime); + if (result == 0) + result = m_RotationDirection.compare(myRhs->m_RotationDirection); + if (result == 0) + result = m_SingleCollimationWidth.compare(myRhs->m_SingleCollimationWidth); + if (result == 0) + result = m_TableHeight.compare(myRhs->m_TableHeight); + if (result == 0) + result = m_TotalCollimationWidth.compare(myRhs->m_TotalCollimationWidth); + return result; +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getDataCollectionDiameter(Float64& value, + const unsigned long pos) +{ + return m_DataCollectionDiameter.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getGantryDetectorTilt(Float64& value, + const unsigned long pos) +{ + return m_GantryDetectorTilt.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getReferencedPathIndex(OFVector& values) +{ + return DcmIODUtil::getUint16ValuesFromElement(m_ReferencedPathIndex, values); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getReferencedPathIndex(Uint16& value, + const unsigned long pos) +{ + return m_ReferencedPathIndex.getUint16(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getRevolutionTime(Float64& value, + const unsigned long pos) +{ + return m_RevolutionTime.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getRotationDirection( + FGCTAcquisitionDetails::E_RotationDirection& value, const long pos) +{ + OFString str; + DcmIODUtil::getStringValueFromElement(m_RotationDirection, str, pos); + value = rotaDir2Enum(str); + if ((value != FGCTAcquisitionDetails::E_RotationDirection_Empty) + && (value != FGCTAcquisitionDetails::E_RotationDirection_Invalid)) + return EC_Normal; + else + return EC_InvalidValue; +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getRotationDirection(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_RotationDirection, value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getSingleCollimationWidth(Float64& value, + const unsigned long pos) +{ + return m_SingleCollimationWidth.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getTableHeight(Float64& value, const unsigned long pos) +{ + return m_TableHeight.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::getTotalCollimationWidth(Float64& value, + const unsigned long pos) +{ + return m_TotalCollimationWidth.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(item, m_ReferencedPathIndex, "1-n", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_RotationDirection, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_RevolutionTime, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_SingleCollimationWidth, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_TotalCollimationWidth, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_TableHeight, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_GantryDetectorTilt, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_DataCollectionDiameter, "1", "1C", "CTAcquisitionDetailsMacro"); + + return EC_Normal; +} + +FGCTAcquisitionDetails::E_RotationDirection +FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::rotaDir2Enum(const OFString& str) +{ + if (str == "CC") + return E_RotationDirection_CC; + else if (str == "CW") + return E_RotationDirection_CW; + else if (str.empty()) + return E_RotationDirection_Empty; + else + return E_RotationDirection_Invalid; +} + +OFBool +FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::rotaDir2Str(const FGCTAcquisitionDetails::E_RotationDirection& rota, + OFString& result) +{ + switch (rota) + { + case FGCTAcquisitionDetails::E_RotationDirection_CC: + result = "CC"; + break; + case FGCTAcquisitionDetails::E_RotationDirection_CW: + result = "CW"; + break; + case FGCTAcquisitionDetails::E_RotationDirection_Empty: + result = ""; + break; + case FGCTAcquisitionDetails::E_RotationDirection_Invalid: + result = ""; + return OFFalse; + default: + result = ""; + DCMFG_WARN("Unknown value for enum FGCTAcquisitionDetails::E_RotationDirection: " << rota); + return OFFalse; + } + return OFTrue; +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setDataCollectionDiameter(const Float64 value, + const OFBool checkValue) +{ + (void)checkValue; + return m_DataCollectionDiameter.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setGantryDetectorTilt(const Float64 value, + const OFBool checkValue) +{ + (void)checkValue; + return m_GantryDetectorTilt.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setReferencedPathIndex(const OFVector& values, + const OFBool checkValues) +{ + (void)checkValues; + return DcmIODUtil::setUint16ValuesOnElement(m_ReferencedPathIndex, values, "1-n", checkValues); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setRotationDirection( + const FGCTAcquisitionDetails::E_RotationDirection& value, const OFBool checkValue) +{ + (void)checkValue; + OFString val; + if (rotaDir2Str(value, val)) + { + return m_RotationDirection.putOFStringArray(val); + } + else + return FG_EC_InvalidData; +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setRevolutionTime(const Float64 value, + const bool checkValue) +{ + (void)checkValue; + return m_RevolutionTime.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setSingleCollimationWidth(const Float64 value, + const OFBool checkValue) +{ + (void)checkValue; + return m_SingleCollimationWidth.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setTableHeight(const Float64 value, + const OFBool checkValue) +{ + (void)checkValue; + return m_TableHeight.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::setTotalCollimationWidth(const Float64 value, + const OFBool checkValue) +{ + (void)checkValue; + return m_TotalCollimationWidth.putFloat64(value); +} + +OFCondition FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::write(DcmItem& item) +{ + // --- write frame content macro attributes --- + OFCondition result; + DcmIODUtil::copyElementToDataset(result, item, m_ReferencedPathIndex, "1-n", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_RotationDirection, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_RevolutionTime, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_SingleCollimationWidth, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_TotalCollimationWidth, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_TableHeight, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_GantryDetectorTilt, "1", "1C", "CTAcquisitionDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_DataCollectionDiameter, "1", "1C", "CTAcquisitionDetailsMacro"); + + return result; +} + +FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem::clone() const +{ + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* copy = new FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem(); + if (copy) + { + copy->m_ReferencedPathIndex = this->m_ReferencedPathIndex; + copy->m_RotationDirection = this->m_RotationDirection; + copy->m_RevolutionTime = this->m_RevolutionTime; + copy->m_SingleCollimationWidth = this->m_SingleCollimationWidth; + copy->m_TotalCollimationWidth = this->m_TotalCollimationWidth; + copy->m_TableHeight = this->m_TableHeight; + copy->m_GantryDetectorTilt = this->m_GantryDetectorTilt; + copy->m_DataCollectionDiameter = this->m_DataCollectionDiameter; + } + return copy; +} diff --git a/dcmfg/libsrc/fgctacquisitiontype.cc b/dcmfg/libsrc/fgctacquisitiontype.cc new file mode 100644 index 00000000..d0b0e418 --- /dev/null +++ b/dcmfg/libsrc/fgctacquisitiontype.cc @@ -0,0 +1,303 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Acquisition Type Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctacquisitiontype.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString FGCTAcquisitionType::DT_AcquisitionType_Sequenced = "SEQUENCED"; +const OFString FGCTAcquisitionType::DT_AcquisitionType_Spiral = "SPIRAL"; +const OFString FGCTAcquisitionType::DT_AcquisitionType_ConstantAngle = "CONSTANT_ANGLE"; +const OFString FGCTAcquisitionType::DT_AcquisitionType_Stationary = "STATIONARY"; +const OFString FGCTAcquisitionType::DT_AcquisitionType_Free = "FREE"; + +// Constructor +FGCTAcquisitionType::FGCTAcquisitionType() + : FGBase(DcmFGTypes::EFG_CTACQUISITIONTYPE) + , m_AcquisitionType(DCM_AcquisitionType) + , m_TubeAngle(DCM_TubeAngle) + , m_ConstantVolumeFlag(DCM_ConstantVolumeFlag) + , m_FluoroscopyFlag(DCM_FluoroscopyFlag) +{ +} + +FGCTAcquisitionType::~FGCTAcquisitionType() +{ + // nothing to do +} + +FGBase* FGCTAcquisitionType::clone() const +{ + FGCTAcquisitionType* copy = new FGCTAcquisitionType(); + if (copy) + { + copy->m_AcquisitionType = this->m_AcquisitionType; + copy->m_TubeAngle = this->m_TubeAngle; + copy->m_ConstantVolumeFlag = this->m_ConstantVolumeFlag; + copy->m_FluoroscopyFlag = this->m_FluoroscopyFlag; + } + return copy; +} + +void FGCTAcquisitionType::clearData() +{ + m_AcquisitionType.clear(); + m_TubeAngle.clear(); + m_ConstantVolumeFlag.clear(); + m_FluoroscopyFlag.clear(); +} + +OFCondition FGCTAcquisitionType::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Acquisition Type Sequence from given item +OFCondition FGCTAcquisitionType::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_CTAcquisitionTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_AcquisitionType, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TubeAngle, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ConstantVolumeFlag, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FluoroscopyFlag, "1", "1", "CTAcquisitionTypeMacro"); + return EC_Normal; +} + +/// Writes single CT Acquisition Type Sequence into given item +OFCondition FGCTAcquisitionType::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_CTAcquisitionTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_AcquisitionType, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_TubeAngle, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ConstantVolumeFlag, "1", "1", "CTAcquisitionTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FluoroscopyFlag, "1", "1", "CTAcquisitionTypeMacro"); + return result; +} + +int FGCTAcquisitionType::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTAcquisitionType* myRhs = OFstatic_cast(const FGCTAcquisitionType*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_AcquisitionType.compare(myRhs->m_AcquisitionType); + if (result == 0) + result = m_TubeAngle.compare(myRhs->m_TubeAngle); + if (result == 0) + result = m_ConstantVolumeFlag.compare(myRhs->m_ConstantVolumeFlag); + if (result == 0) + result = m_FluoroscopyFlag.compare(myRhs->m_FluoroscopyFlag); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTAcquisitionType::getAcquisitionType(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AcquisitionType, value, pos); +} + +OFCondition FGCTAcquisitionType::getTubeAngle(Float64& value, const unsigned long pos) +{ + return m_TubeAngle.getFloat64(value, pos); +} + +OFCondition FGCTAcquisitionType::getConstantVolumeFlag(FGCTAcquisitionType::E_ConstantVolumeFlag& value, const long pos) +{ + OFString str; + DcmIODUtil::getStringValueFromElement(m_ConstantVolumeFlag, str, pos); + value = constVolFlag2Enum(str); + if ((value != FGCTAcquisitionType::E_ConstVol_Empty) && (value != FGCTAcquisitionType::E_ConstVol_Invalid)) + return EC_Normal; + else + return EC_InvalidValue; +} + +OFCondition FGCTAcquisitionType::getConstantVolumeFlag(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ConstantVolumeFlag, value, pos); +} + +OFCondition FGCTAcquisitionType::getFluoroscopyFlag(FGCTAcquisitionType::E_FluoroscopyFlag& value, const long pos) +{ + OFString str; + DcmIODUtil::getStringValueFromElement(m_FluoroscopyFlag, str, pos); + value = fluoroscopyFlag2Enum(str); + if ((value != FGCTAcquisitionType::E_Fluoroscopy_Empty) && (value != FGCTAcquisitionType::E_Fluoroscopy_Invalid)) + return EC_Normal; + else + return EC_InvalidValue; +} + +OFCondition FGCTAcquisitionType::getFluoroscopyFlag(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FluoroscopyFlag, value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTAcquisitionType::setAcquisitionType(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AcquisitionType.putOFStringArray(value); + return result; +} + +OFCondition FGCTAcquisitionType::setTubeAngle(const Float64& value, const OFBool checkValue) +{ + return m_TubeAngle.putFloat64(value); +} + +OFCondition FGCTAcquisitionType::setConstantVolumeFlag(const FGCTAcquisitionType::E_ConstantVolumeFlag& value, + const OFBool checkValue) +{ + (void)checkValue; + OFString val; + if (constVolFlag2Str(value, val)) + { + return m_ConstantVolumeFlag.putOFStringArray(val); + } + else + return FG_EC_InvalidData; +} + +OFCondition FGCTAcquisitionType::setConstantVolumeFlag(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ConstantVolumeFlag.putOFStringArray(value); + return result; +} + +OFCondition FGCTAcquisitionType::setFluoroscopyFlag(const FGCTAcquisitionType::E_FluoroscopyFlag& value, + const OFBool checkValue) +{ + (void)checkValue; + OFString val; + if (fluoroscopyFlag2Str(value, val)) + { + return m_FluoroscopyFlag.putOFStringArray(val); + } + else + return FG_EC_InvalidData; +} + +OFCondition FGCTAcquisitionType::setFluoroscopyFlag(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FluoroscopyFlag.putOFStringArray(value); + return result; +} + +FGCTAcquisitionType::E_ConstantVolumeFlag FGCTAcquisitionType::constVolFlag2Enum(const OFString& str) +{ + if (str == "NO") + return E_ConstVol_No; + else if (str == "YES") + return E_ConstVol_Yes; + else if (str.empty()) + return E_ConstVol_Empty; + else + return E_ConstVol_Invalid; +} + +OFBool FGCTAcquisitionType::constVolFlag2Str(const FGCTAcquisitionType::E_ConstantVolumeFlag& eval, OFString& result) +{ + switch (eval) + { + case FGCTAcquisitionType::E_ConstVol_No: + result = "NO"; + break; + case FGCTAcquisitionType::E_ConstVol_Yes: + result = "YES"; + break; + case FGCTAcquisitionType::E_ConstVol_Empty: + result = ""; + break; + case FGCTAcquisitionType::E_ConstVol_Invalid: + result = ""; + return OFFalse; + default: + result = ""; + DCMFG_WARN("Unknown value for enum FGCTAcquisitionType::E_ConstantVolumeFlag: " << eval); + return OFFalse; + } + return OFTrue; +} + +FGCTAcquisitionType::E_FluoroscopyFlag FGCTAcquisitionType::fluoroscopyFlag2Enum(const OFString& str) +{ + if (str == "NO") + return E_Fluoroscopy_No; + else if (str == "YES") + return E_Fluoroscopy_Yes; + else if (str.empty()) + return E_Fluoroscopy_Empty; + else + return E_Fluoroscopy_Invalid; +} + +OFBool FGCTAcquisitionType::fluoroscopyFlag2Str(const FGCTAcquisitionType::E_FluoroscopyFlag& eval, OFString& result) +{ + switch (eval) + { + case FGCTAcquisitionType::E_Fluoroscopy_No: + result = "NO"; + break; + case FGCTAcquisitionType::E_Fluoroscopy_Yes: + result = "YES"; + break; + case FGCTAcquisitionType::E_Fluoroscopy_Empty: + result = ""; + break; + case FGCTAcquisitionType::E_Fluoroscopy_Invalid: + result = ""; + return OFFalse; + default: + result = ""; + DCMFG_WARN("Unknown value for enum FGCTAcquisitionType::E_FluoroscopyFlag: " << eval); + return OFFalse; + } + return OFTrue; +} diff --git a/dcmfg/libsrc/fgctadditionalxraysource.cc b/dcmfg/libsrc/fgctadditionalxraysource.cc new file mode 100644 index 00000000..b29ebd6a --- /dev/null +++ b/dcmfg/libsrc/fgctadditionalxraysource.cc @@ -0,0 +1,362 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Additional X-Ray Source + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctadditionalxraysource.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +FGCTAdditionalXRaySource::FGCTAdditionalXRaySource() + : FGBase(DcmFGTypes::EFG_CTADDITIONALXRAYSOURCE) + , m_Items() +{ +} + +OFCondition FGCTAdditionalXRaySource::check() const +{ + // TODO Maybe add checks later + return EC_Normal; +} + +void FGCTAdditionalXRaySource::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +int FGCTAdditionalXRaySource::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + FGCTAdditionalXRaySource* myRhs + = OFconst_cast(FGCTAdditionalXRaySource*, (OFstatic_cast(const FGCTAdditionalXRaySource*, &rhs))); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(m_Items, myRhs->getCTAdditionalXRaySourceItems()); +} + +OFCondition FGCTAdditionalXRaySource::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTAdditionalXRaySourceSequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTAdditionalXRaySourceSequence, num, seqItem).good()) + { + FGCTAdditionalXRaySourceItem* newItem = new FGCTAdditionalXRaySourceItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +OFCondition FGCTAdditionalXRaySource::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence( + result, DCM_CTAdditionalXRaySourceSequence, m_Items, item, "1-n", "2", "CT Additional X-Ray Source"); + } + + return result; +} + +FGBase* FGCTAdditionalXRaySource::clone() const +{ + OFunique_ptr copy(new FGCTAdditionalXRaySource()); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +OFVector& +FGCTAdditionalXRaySource::getCTAdditionalXRaySourceItems() +{ + return m_Items; +} + +FGCTAdditionalXRaySource::~FGCTAdditionalXRaySource() +{ + clearData(); +} + +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::FGCTAdditionalXRaySourceItem() + : m_KVP(DCM_KVP) + , m_XRayTubeCurrentInmA(DCM_XRayTubeCurrentInmA) + , m_DataCollectionDiameter(DCM_DataCollectionDiameter) + , m_FocalSpots(DCM_FocalSpots) + , m_FilterType(DCM_FilterType) + , m_FilterMaterial(DCM_FilterMaterial) + , m_ExposureInmAs(DCM_ExposureInmAs) + , m_EnergyWeightingFactor(DCM_EnergyWeightingFactor) +{ +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::check() const +{ + // TODO: Maybe add checks lager + return EC_Normal; +} + +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::~FGCTAdditionalXRaySourceItem() +{ + // nothing to do +} + +void FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::clearData() +{ + m_KVP.clear(); + m_XRayTubeCurrentInmA.clear(); + m_DataCollectionDiameter.clear(); + m_FocalSpots.clear(); + m_FilterType.clear(); + m_FilterMaterial.clear(); + m_ExposureInmAs.clear(); + m_EnergyWeightingFactor.clear(); +} + +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem* +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::clone() const +{ + if (FGCTAdditionalXRaySourceItem* copy = new FGCTAdditionalXRaySourceItem) + { + copy->m_KVP = m_KVP; + copy->m_XRayTubeCurrentInmA = m_XRayTubeCurrentInmA; + copy->m_DataCollectionDiameter = m_DataCollectionDiameter; + copy->m_FocalSpots = m_FocalSpots; + copy->m_FilterType = m_FilterType; + copy->m_FilterMaterial = m_FilterMaterial; + copy->m_ExposureInmAs = m_ExposureInmAs; + copy->m_EnergyWeightingFactor = m_EnergyWeightingFactor; + return copy; + } + return OFnullptr; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::read(DcmItem& item) +{ + clearData(); + + OFCondition result; + + DcmIODUtil::getAndCheckElementFromDataset(item, m_KVP, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_XRayTubeCurrentInmA, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_DataCollectionDiameter, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FocalSpots, "1-n", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FilterType, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FilterMaterial, "1-n", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_ExposureInmAs, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_EnergyWeightingFactor, "1", "1C", "CT Additional X-Ray Source"); + + return EC_Normal; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.bad()) + return result; + + DcmIODUtil::copyElementToDataset(result, item, m_KVP, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_XRayTubeCurrentInmA, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_DataCollectionDiameter, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_FocalSpots, "1-n", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_FilterType, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_FilterMaterial, "1-n", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_ExposureInmAs, "1", "1", "CT Additional X-Ray Source"); + DcmIODUtil::copyElementToDataset(result, item, m_EnergyWeightingFactor, "1", "1C", "CT Additional X-Ray Source"); + + return result; +} + +int FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::compare( + const FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem& rhs) const +{ + int result = 0; + const FGCTAdditionalXRaySourceItem* myRhs = OFstatic_cast(const FGCTAdditionalXRaySourceItem*, &rhs); + + // Compare all elements + result = m_KVP.compare(myRhs->m_KVP); + if (result == 0) + result = m_XRayTubeCurrentInmA.compare(myRhs->m_XRayTubeCurrentInmA); + if (result == 0) + result = m_DataCollectionDiameter.compare(myRhs->m_DataCollectionDiameter); + if (result == 0) + result = m_FocalSpots.compare(myRhs->m_FocalSpots); + if (result == 0) + result = m_FilterType.compare(myRhs->m_FilterType); + if (result == 0) + result = m_FilterMaterial.compare(myRhs->m_FilterMaterial); + if (result == 0) + result = m_ExposureInmAs.compare(myRhs->m_ExposureInmAs); + if (result == 0) + result = m_EnergyWeightingFactor.compare(myRhs->m_EnergyWeightingFactor); + + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getKVP(OFString& value, const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_KVP, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getXRayTubeCurrentInmA(Float64& value, + const unsigned long pos) const +{ + return DcmIODUtil::getFloat64ValueFromElement(m_XRayTubeCurrentInmA, value, pos); +} + +OFCondition +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getDataCollectionDiameter(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_DataCollectionDiameter, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getFocalSpots(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_FocalSpots, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getFilterType(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_FilterType, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getFilterMaterial(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_FilterMaterial, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getExposureInmAs(Float64& value, + const unsigned long pos) const +{ + return DcmIODUtil::getFloat64ValueFromElement(m_ExposureInmAs, value, pos); +} + +OFCondition +FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::getEnergyWeightingFactor(Float32& value, + const unsigned long pos) const +{ + return DcmIODUtil::getFloat32ValueFromElement(m_EnergyWeightingFactor, value, pos); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setKVP(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_KVP.putString(value.c_str()); + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setKVP(const Float64 value, const OFBool checkValue) +{ + (void)checkValue; + return m_KVP.putFloat64(value); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setXRayTubeCurrentInmA(const Float64 value, + const OFBool checkValue) +{ + return m_XRayTubeCurrentInmA.putFloat64(value); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setDataCollectionDiameter(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_DataCollectionDiameter.putString(value.c_str()); + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setDataCollectionDiameter(const Float64 value, + const OFBool checkValue) +{ + return m_DataCollectionDiameter.putFloat64(value); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setFocalSpots(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FocalSpots.putString(value.c_str()); + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setFocalSpots(const OFVector& values, + const OFBool checkValue) +{ + return DcmIODUtil::setFloat64ValuesOnElement(m_FocalSpots, values, "1-n", checkValue); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setFilterType(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FilterType.putString(value.c_str()); + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setFilterMaterial(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FilterMaterial.putString(value.c_str()); + return result; +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setExposureInmAs(const Float64 value, + const OFBool checkValue) +{ + return m_ExposureInmAs.putFloat64(value); +} + +OFCondition FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem::setEnergyWeightingFactor(const Float32 value, + const OFBool checkValue) +{ + return m_EnergyWeightingFactor.putFloat32(value); +} diff --git a/dcmfg/libsrc/fgctexposure.cc b/dcmfg/libsrc/fgctexposure.cc new file mode 100644 index 00000000..c56f92cb --- /dev/null +++ b/dcmfg/libsrc/fgctexposure.cc @@ -0,0 +1,459 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Exposure Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctexposure.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTExposure::FGCTExposureItem::FGCTExposureItem() + : m_ReferencedPathIndex(DCM_ReferencedPathIndex) + , m_ExposureTimeInMs(DCM_ExposureTimeInms) + , m_XRayTubeCurrentInMa(DCM_XRayTubeCurrentInmA) + , m_ExposureInMas(DCM_ExposureInmAs) + , m_ExposureModulationType(DCM_ExposureModulationType) + , m_EstimatedDoseSaving(DCM_EstimatedDoseSaving) + , m_CTDIVol(DCM_CTDIvol) + , m_CTDIPhantomTypeCodeSequence() + , m_WaterEquivalentDiameter(DCM_WaterEquivalentDiameter) + , m_WaterEquivalentDiameterCalculationMethodCodeSequence() + , m_ImageAndFluoroscopyAreaDoseProduct(DCM_ImageAndFluoroscopyAreaDoseProduct) +{ +} + +FGCTExposure::FGCTExposureItem::FGCTExposureItem(const FGCTExposureItem& rhs) + : m_ReferencedPathIndex(rhs.m_ReferencedPathIndex) + , m_ExposureTimeInMs(rhs.m_ExposureTimeInMs) + , m_XRayTubeCurrentInMa(rhs.m_XRayTubeCurrentInMa) + , m_ExposureInMas(rhs.m_ExposureInMas) + , m_ExposureModulationType(rhs.m_ExposureModulationType) + , m_EstimatedDoseSaving(rhs.m_EstimatedDoseSaving) + , m_CTDIVol(rhs.m_CTDIVol) + , m_CTDIPhantomTypeCodeSequence() + , m_WaterEquivalentDiameter(rhs.m_WaterEquivalentDiameter) + , m_WaterEquivalentDiameterCalculationMethodCodeSequence() + , m_ImageAndFluoroscopyAreaDoseProduct(rhs.m_ImageAndFluoroscopyAreaDoseProduct) +{ + DcmIODUtil::copyContainer(rhs.m_CTDIPhantomTypeCodeSequence, this->m_CTDIPhantomTypeCodeSequence); + DcmIODUtil::copyContainer(rhs.m_WaterEquivalentDiameterCalculationMethodCodeSequence, + this->m_WaterEquivalentDiameterCalculationMethodCodeSequence); +} + +FGCTExposure::FGCTExposureItem::~FGCTExposureItem() +{ + DcmIODUtil::freeContainer(m_CTDIPhantomTypeCodeSequence); + DcmIODUtil::freeContainer(m_WaterEquivalentDiameterCalculationMethodCodeSequence); +} + +FGCTExposure::FGCTExposureItem* FGCTExposure::FGCTExposureItem::clone() const +{ + OFCondition result; + OFunique_ptr copy(new FGCTExposureItem); + if (copy) + { + copy->m_ReferencedPathIndex = this->m_ReferencedPathIndex; + copy->m_ExposureTimeInMs = this->m_ExposureTimeInMs; + copy->m_XRayTubeCurrentInMa = this->m_XRayTubeCurrentInMa; + copy->m_ExposureInMas = this->m_ExposureInMas; + copy->m_ExposureModulationType = this->m_ExposureModulationType; + copy->m_EstimatedDoseSaving = this->m_EstimatedDoseSaving; + copy->m_CTDIVol = this->m_CTDIVol; + copy->m_WaterEquivalentDiameter = this->m_WaterEquivalentDiameter; + copy->m_ImageAndFluoroscopyAreaDoseProduct = this->m_ImageAndFluoroscopyAreaDoseProduct; + // Copy sequences + result = DcmIODUtil::copyContainer(this->m_CTDIPhantomTypeCodeSequence, copy->m_CTDIPhantomTypeCodeSequence); + if (result.good()) + DcmIODUtil::copyContainer(this->m_WaterEquivalentDiameterCalculationMethodCodeSequence, + copy->m_WaterEquivalentDiameterCalculationMethodCodeSequence); + if (result.good()) + return copy.release(); + } + return OFnullptr; +} + +void FGCTExposure::FGCTExposureItem::clearData() +{ + m_ReferencedPathIndex.clear(); + m_ExposureTimeInMs.clear(); + m_XRayTubeCurrentInMa.clear(); + m_ExposureInMas.clear(); + m_ExposureModulationType.clear(); + m_EstimatedDoseSaving.clear(); + m_CTDIVol.clear(); + m_WaterEquivalentDiameter.clear(); + m_ImageAndFluoroscopyAreaDoseProduct.clear(); + // clear sequences + DcmIODUtil::freeContainer(m_CTDIPhantomTypeCodeSequence); + DcmIODUtil::freeContainer(m_WaterEquivalentDiameterCalculationMethodCodeSequence); +} + +OFCondition FGCTExposure::FGCTExposureItem::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Exposure Sequence from given item +OFCondition FGCTExposure::FGCTExposureItem::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(item, m_ReferencedPathIndex, "1-n", "1C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_ExposureTimeInMs, "1", "1C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_XRayTubeCurrentInMa, "1", "1C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_ExposureInMas, "1", "1C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_ExposureModulationType, "1-n", "1C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_EstimatedDoseSaving, "1", "2C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_CTDIVol, "1", "2C", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_WaterEquivalentDiameter, "1", "3", "CTExposureMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_ImageAndFluoroscopyAreaDoseProduct, "1", "3", "CTExposureMacro"); + + DcmIODUtil::readSubSequence( + item, DCM_CTDIPhantomTypeCodeSequence, m_CTDIPhantomTypeCodeSequence, "1", "3", "CTExposureMacro"); + DcmIODUtil::readSubSequence(item, + DCM_WaterEquivalentDiameterCalculationMethodCodeSequence, + m_WaterEquivalentDiameterCalculationMethodCodeSequence, + "1", + "3", + "CTExposureMacro"); + + return EC_Normal; +} + +/// Writes single CT Exposure Sequence into given item +OFCondition FGCTExposure::FGCTExposureItem::write(DcmItem& item) +{ + OFCondition result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, item, m_ReferencedPathIndex, "1-n", "1C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_ExposureTimeInMs, "1", "1C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_XRayTubeCurrentInMa, "1", "1C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_ExposureInMas, "1", "1C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_ExposureModulationType, "1-n", "1C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_EstimatedDoseSaving, "1", "2C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_CTDIVol, "1", "2C", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_WaterEquivalentDiameter, "1", "3", "CTExposureMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_ImageAndFluoroscopyAreaDoseProduct, "1", "3", "CTExposureMacro"); + DcmIODUtil::writeSubSequence( + result, DCM_CTDIPhantomTypeCodeSequence, m_CTDIPhantomTypeCodeSequence, item, "1", "3", "CTExposureMacro"); + DcmIODUtil::writeSubSequence(result, + DCM_WaterEquivalentDiameterCalculationMethodCodeSequence, + m_WaterEquivalentDiameterCalculationMethodCodeSequence, + item, + "1", + "3", + "CTExposureMacro"); + + return result; +} + +int FGCTExposure::FGCTExposureItem::compare(const FGCTExposure::FGCTExposureItem& rhs) const +{ + FGCTExposureItem* myRhs = OFconst_cast(FGCTExposureItem*, OFstatic_cast(const FGCTExposureItem*, &rhs)); + if (!myRhs) + return -1; + + // Compare all elements + int result = m_ReferencedPathIndex.compare(myRhs->m_ReferencedPathIndex); + if (result == 0) + result = m_ExposureTimeInMs.compare(myRhs->m_ExposureTimeInMs); + if (result == 0) + result = m_XRayTubeCurrentInMa.compare(myRhs->m_XRayTubeCurrentInMa); + if (result == 0) + result = m_ExposureInMas.compare(myRhs->m_ExposureInMas); + if (result == 0) + result = m_ExposureModulationType.compare(myRhs->m_ExposureModulationType); + if (result == 0) + result = m_EstimatedDoseSaving.compare(myRhs->m_EstimatedDoseSaving); + if (result == 0) + result = m_CTDIVol.compare(myRhs->m_CTDIVol); + if (result == 0) + result = m_WaterEquivalentDiameter.compare(myRhs->m_WaterEquivalentDiameter); + if (result == 0) + result = m_ImageAndFluoroscopyAreaDoseProduct.compare(myRhs->m_ImageAndFluoroscopyAreaDoseProduct); + if (result == 0) + result = DcmIODUtil::compareContainer(m_CTDIPhantomTypeCodeSequence, myRhs->m_CTDIPhantomTypeCodeSequence); + if (result == 0) + result = DcmIODUtil::compareContainer(m_WaterEquivalentDiameterCalculationMethodCodeSequence, + myRhs->m_WaterEquivalentDiameterCalculationMethodCodeSequence); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTExposure::FGCTExposureItem::getReferencedPathIndex(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReferencedPathIndex, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getExposureTimeInMs(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ExposureTimeInMs, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getExposureTimeInMs(Float64& value, const unsigned long pos) +{ + return m_ExposureTimeInMs.getFloat64(value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getXRayTubeCurrentInMa(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_XRayTubeCurrentInMa, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getXRayTubeCurrentInMa(Float64& value, const unsigned long pos) +{ + return m_XRayTubeCurrentInMa.getFloat64(value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getExposureInMas(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ExposureInMas, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getExposureInMas(Float64& value, const unsigned long pos) +{ + return m_ExposureInMas.getFloat64(value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getExposureModulationType(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ExposureModulationType, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getEstimatedDoseSaving(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_EstimatedDoseSaving, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getEstimatedDoseSaving(Float64& value, const unsigned long pos) +{ + return m_EstimatedDoseSaving.getFloat64(value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getCTDIVol(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_CTDIVol, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getCTDIVol(Float64& value, const unsigned long pos) +{ + return m_CTDIVol.getFloat64(value, pos); +} + +OFVector& FGCTExposure::FGCTExposureItem::getCTDIPhantomTypeCodeSequence() +{ + return m_CTDIPhantomTypeCodeSequence; +} + +OFCondition FGCTExposure::FGCTExposureItem::getWaterEquivalentDiameter(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_WaterEquivalentDiameter, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getWaterEquivalentDiameter(Float64& value, const unsigned long pos) +{ + return m_WaterEquivalentDiameter.getFloat64(value, pos); +} + +OFVector& FGCTExposure::FGCTExposureItem::getWaterEquivalentDiameterCalculationMethodCodeSequence() +{ + return m_WaterEquivalentDiameterCalculationMethodCodeSequence; +} + +OFCondition FGCTExposure::FGCTExposureItem::getImageAndFluoroscopyAreaDoseProduct(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ImageAndFluoroscopyAreaDoseProduct, value, pos); +} + +OFCondition FGCTExposure::FGCTExposureItem::getImageAndFluoroscopyAreaDoseProduct(Float64& value, + const unsigned long pos) +{ + return m_ImageAndFluoroscopyAreaDoseProduct.getFloat64(value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTExposure::FGCTExposureItem::setReferencedPathIndex(const OFVector& values, + const bool checkValues) +{ + (void)checkValues; + return DcmIODUtil::setUint16ValuesOnElement(m_ReferencedPathIndex, values, "1-n", checkValues); +} + +OFCondition FGCTExposure::FGCTExposureItem::setExposureTimeInMs(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_ExposureTimeInMs.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setXRayTubeCurrentInMa(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_XRayTubeCurrentInMa.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setExposureInMas(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_ExposureInMas.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setExposureModulationType(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_ExposureModulationType.putString(value.c_str()); + return result; +} + +OFCondition FGCTExposure::FGCTExposureItem::setEstimatedDoseSaving(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_EstimatedDoseSaving.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setCTDIVol(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_CTDIVol.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setWaterEquivalentDiameter(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_WaterEquivalentDiameter.putFloat64(value); +} + +OFCondition FGCTExposure::FGCTExposureItem::setImageAndFluoroscopyAreaDoseProduct(const Float64 value, + const bool checkValue) +{ + (void)checkValue; + return m_ImageAndFluoroscopyAreaDoseProduct.putFloat64(value); +} + +// --------------------- + +// Constructor +FGCTExposure::FGCTExposure() + : FGBase(DcmFGTypes::EFG_CTEXPOSURE) + , m_Items() +{ +} + +FGCTExposure::FGCTExposure(const FGCTExposure& rhs) + : FGBase(rhs) + , m_Items() +{ + OFCondition result = DcmIODUtil::copyContainer(rhs.m_Items, this->m_Items); + if (result.bad()) + { + DCMFG_ERROR("Cannot copy FGCTExposure class: " << result.text()); + } +} + +FGCTExposure::~FGCTExposure() +{ + DcmIODUtil::freeContainer(m_Items); +} + +FGBase* FGCTExposure::clone() const +{ + OFunique_ptr copy(new FGCTExposure()); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +void FGCTExposure::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +OFCondition FGCTExposure::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Exposure Sequence from given item +OFCondition FGCTExposure::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTExposureSequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTExposureSequence, num, seqItem).good()) + { + FGCTExposureItem* newItem = new FGCTExposureItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +/// Writes single CT Exposure Sequence into given item +OFCondition FGCTExposure::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence(result, DCM_CTExposureSequence, m_Items, item, "1-n", "2", "CTGeometryMacro"); + } + return result; +} + +int FGCTExposure::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTExposure* myRhs = OFstatic_cast(const FGCTExposure*, &rhs); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(this->m_Items, myRhs->m_Items); +} + +OFVector& FGCTExposure::getCTExposureItems() +{ + return m_Items; +} diff --git a/dcmfg/libsrc/fgctgeometry.cc b/dcmfg/libsrc/fgctgeometry.cc new file mode 100644 index 00000000..28de4184 --- /dev/null +++ b/dcmfg/libsrc/fgctgeometry.cc @@ -0,0 +1,250 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Geometry Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctgeometry.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTGeometry::FGCTGeometryItem::FGCTGeometryItem() + : m_ReferencedPathIndex(DCM_ReferencedPathIndex) + , m_DistanceSourceToDetector(DCM_DistanceSourceToDetector) + , m_DistanceSourceToDataCollectionCenter(DCM_DistanceSourceToDataCollectionCenter) +{ +} + +FGCTGeometry::FGCTGeometryItem::~FGCTGeometryItem() +{ + // nothing to do +} + +FGCTGeometry::FGCTGeometryItem* FGCTGeometry::FGCTGeometryItem::clone() const +{ + FGCTGeometryItem* copy = new FGCTGeometryItem(); + if (copy) + { + copy->m_ReferencedPathIndex = this->m_ReferencedPathIndex; + copy->m_DistanceSourceToDetector = this->m_DistanceSourceToDetector; + copy->m_DistanceSourceToDataCollectionCenter = this->m_DistanceSourceToDataCollectionCenter; + } + return copy; +} + +void FGCTGeometry::FGCTGeometryItem::clearData() +{ + m_ReferencedPathIndex.clear(); + m_DistanceSourceToDetector.clear(); + m_DistanceSourceToDataCollectionCenter.clear(); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Geometry Sequence from given item +OFCondition FGCTGeometry::FGCTGeometryItem::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(item, m_ReferencedPathIndex, "1-n", "1C", "CTGeometryMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_DistanceSourceToDetector, "1", "1C", "CTGeometryMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + item, m_DistanceSourceToDataCollectionCenter, "1", "1C", "CTGeometryMacro"); + return EC_Normal; +} + +/// Writes single CT Geometry Sequence into given item +OFCondition FGCTGeometry::FGCTGeometryItem::write(DcmItem& item) +{ + OFCondition result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, item, m_ReferencedPathIndex, "1-n", "1C", "CTGeometryMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_DistanceSourceToDetector, "1", "1C", "CTGeometryMacro"); + DcmIODUtil::copyElementToDataset( + result, item, m_DistanceSourceToDataCollectionCenter, "1", "1C", "CTGeometryMacro"); + return result; +} + +int FGCTGeometry::FGCTGeometryItem::compare(const FGCTGeometry::FGCTGeometryItem& rhs) const +{ + const FGCTGeometry::FGCTGeometryItem* myRhs = OFstatic_cast(const FGCTGeometry::FGCTGeometryItem*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + int result = m_ReferencedPathIndex.compare(myRhs->m_ReferencedPathIndex); + if (result == 0) + result = m_DistanceSourceToDetector.compare(myRhs->m_DistanceSourceToDetector); + if (result == 0) + result = m_DistanceSourceToDataCollectionCenter.compare(myRhs->m_DistanceSourceToDataCollectionCenter); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTGeometry::FGCTGeometryItem::getReferencedPathIndex(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReferencedPathIndex, value, pos); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::getReferencedPathIndex(OFVector& values) +{ + return DcmIODUtil::getUint16ValuesFromElement(m_ReferencedPathIndex, values); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::getDistanceSourceToDataCollectionCenter(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_DistanceSourceToDataCollectionCenter, value, pos); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::getDistanceSourceToDataCollectionCenter(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_DistanceSourceToDataCollectionCenter, values); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::getDistanceSourceToDetector(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_DistanceSourceToDetector, value, pos); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::getDistanceSourceToDetector(Float64& value, const unsigned long pos) +{ + return m_DistanceSourceToDetector.getFloat64(value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTGeometry::FGCTGeometryItem::setReferencedPathIndex(const OFVector& values, + const bool checkValue) +{ + return DcmIODUtil::setUint16ValuesOnElement(m_ReferencedPathIndex, values, "1-n", checkValue); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::setDistanceSourceToDetector(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_DistanceSourceToDetector.putFloat64(value, 0); +} + +OFCondition FGCTGeometry::FGCTGeometryItem::setDistanceSourceToDataCollectionCenter(const Float64 value, + const bool checkValue) +{ + (void)checkValue; + return m_DistanceSourceToDataCollectionCenter.putFloat64(value, 0); +} + +// ------------------------ + +// Constructor +FGCTGeometry::FGCTGeometry() + : FGBase(DcmFGTypes::EFG_CTGEOMETRY) + , m_Items() +{ +} + +FGCTGeometry::~FGCTGeometry() +{ + clearData(); +} + +FGBase* FGCTGeometry::clone() const +{ + OFunique_ptr copy(new FGCTGeometry); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +void FGCTGeometry::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +OFCondition FGCTGeometry::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Geometry Sequence from given item +OFCondition FGCTGeometry::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTGeometrySequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTGeometrySequence, num, seqItem).good()) + { + FGCTGeometryItem* newItem = new FGCTGeometryItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +/// Writes single CT Geometry Sequence into given item +OFCondition FGCTGeometry::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence(result, DCM_CTGeometrySequence, m_Items, item, "1-n", "2", "CTGeometryMacro"); + } + return result; +} + +int FGCTGeometry::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTGeometry* myRhs = OFstatic_cast(const FGCTGeometry*, &rhs); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(this->m_Items, myRhs->m_Items); +} + +OFVector& FGCTGeometry::getCTGeometryItems() +{ + return m_Items; +} diff --git a/dcmfg/libsrc/fgctimageframetype.cc b/dcmfg/libsrc/fgctimageframetype.cc new file mode 100644 index 00000000..3e52adf9 --- /dev/null +++ b/dcmfg/libsrc/fgctimageframetype.cc @@ -0,0 +1,335 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Image Frame Type Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctimageframetype.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_MaxIp = "MAX_IP"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_MinIp = "MIN_IP"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_VolumeRender = "VOLUME_RENDER"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_SurfaceRender = "SURFACE_RENDER"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_Mpr = "MPR"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_CurvedMpr = "CURVED_MPR"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_None = "NONE"; +const OFString FGCTImageFrameType::DT_VolBasedCalcTechnique_Mixed = "MIXED"; + +// Constructor +FGCTImageFrameType::FGCTImageFrameType() + : FGBase(DcmFGTypes::EFG_CTIMAGEFRAMETYPE) + , m_FrameType(DCM_FrameType) + , m_PixelPresentation(DCM_PixelPresentation) + , m_VolumetricProperties(DCM_VolumetricProperties) + , m_VolumeBasedCalculationTechnique(DCM_VolumeBasedCalculationTechnique) +{ +} + +FGCTImageFrameType::~FGCTImageFrameType() +{ + // nothing to do +} + +FGBase* FGCTImageFrameType::clone() const +{ + FGCTImageFrameType* copy = new FGCTImageFrameType(); + if (copy) + { + copy->m_FrameType = this->m_FrameType; + copy->m_PixelPresentation = this->m_PixelPresentation; + copy->m_VolumetricProperties = this->m_VolumetricProperties; + copy->m_VolumeBasedCalculationTechnique = this->m_VolumeBasedCalculationTechnique; + } + return copy; +} + +void FGCTImageFrameType::clearData() +{ + m_FrameType.clear(); + m_PixelPresentation.clear(); + m_VolumetricProperties.clear(); + m_VolumeBasedCalculationTechnique.clear(); +} + +OFCondition FGCTImageFrameType::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Image Frame Type Sequence from given item +OFCondition FGCTImageFrameType::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_CTImageFrameTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_PixelPresentation, "1", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumetricProperties, "1", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "CTImageFrameTypeMacro"); + return EC_Normal; +} + +/// Writes single CT Image Frame Type Sequence into given item +OFCondition FGCTImageFrameType::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_CTImageFrameTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_PixelPresentation, "1", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumetricProperties, "1", "1", "CTImageFrameTypeMacro"); + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "CTImageFrameTypeMacro"); + return result; +} + +int FGCTImageFrameType::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTImageFrameType* myRhs = OFstatic_cast(const FGCTImageFrameType*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_FrameType.compare(myRhs->m_FrameType); + if (result == 0) + result = m_PixelPresentation.compare(myRhs->m_PixelPresentation); + if (result == 0) + result = m_VolumetricProperties.compare(myRhs->m_VolumetricProperties); + if (result == 0) + result = m_VolumeBasedCalculationTechnique.compare(myRhs->m_VolumeBasedCalculationTechnique); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTImageFrameType::getFrameType(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); +} + +OFCondition FGCTImageFrameType::getPixelPresentation(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_PixelPresentation, value, pos); +} + +OFCondition FGCTImageFrameType::getPixelPresentation(FGCTImageFrameType::E_PixelPresentation& value, const long pos) +{ + OFString str; + DcmIODUtil::getStringValueFromElement(m_PixelPresentation, str, pos); + value = pixelPres2Enum(str); + if ((value != FGCTImageFrameType::E_PixelPres_Empty) && (value != FGCTImageFrameType::E_PixelPres_Invalid)) + return EC_Normal; + else + return EC_InvalidValue; +} + +OFCondition FGCTImageFrameType::getVolumetricProperties(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_VolumetricProperties, value, pos); +} + +OFCondition FGCTImageFrameType::getVolumetricProperties(FGCTImageFrameType::E_VolumetricProperties& value, + const long pos) +{ + OFString str; + DcmIODUtil::getStringValueFromElement(m_VolumetricProperties, str, pos); + value = volProps2Enum(str); + if ((value != FGCTImageFrameType::E_VolProp_Empty) && (value != FGCTImageFrameType::E_VolProp_Invalid)) + return EC_Normal; + else + return EC_InvalidValue; +} + +OFCondition FGCTImageFrameType::getVolumeBasedCalculationTechnique(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_VolumeBasedCalculationTechnique, value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTImageFrameType::setFrameType(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "4") : EC_Normal; + if (result.good()) + result = m_FrameType.putOFStringArray(value); + return result; +} + +OFCondition FGCTImageFrameType::setPixelPresentation(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_PixelPresentation.putOFStringArray(value); + return result; +} + +OFCondition FGCTImageFrameType::setPixelPresentation(const FGCTImageFrameType::E_PixelPresentation& value, + const OFBool checkValue) +{ + (void)checkValue; + OFString val; + if (pixelPres2Str(value, val)) + { + return m_PixelPresentation.putOFStringArray(val); + } + else + return FG_EC_InvalidData; +} + +OFCondition FGCTImageFrameType::setVolumetricProperties(const OFString& value, const OFBool checkValue) +{ + + if (checkValue) + { + if (!volProps2Enum(value)) + return FG_EC_InvalidData; + } + return m_VolumetricProperties.putOFStringArray(value); +} + +OFCondition FGCTImageFrameType::setVolumetricProperties(const FGCTImageFrameType::E_VolumetricProperties& value, + const OFBool checkValue) +{ + (void)checkValue; + OFString val; + if (volProps2Str(value, val)) + { + return m_VolumetricProperties.putOFStringArray(val); + } + else + return FG_EC_InvalidData; +} + +OFCondition FGCTImageFrameType::setVolumeBasedCalculationTechnique(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VolumeBasedCalculationTechnique.putOFStringArray(value); + return result; +} + +FGCTImageFrameType::E_PixelPresentation FGCTImageFrameType::pixelPres2Enum(const OFString& str) +{ + if (str == "COLOR") + return E_PixelPres_Color; + else if (str == "MONOCHROME") + return E_PixelPres_Monochrome; + else if (str == "MIXED") + return E_PixelPres_Mixed; + else if (str == "TRUE_COLOR") + return E_PixelPres_TrueColor; + else if (str.empty()) + return E_PixelPres_Empty; + else + return E_PixelPres_Invalid; +} + +OFBool FGCTImageFrameType::pixelPres2Str(const FGCTImageFrameType::E_PixelPresentation& eval, OFString& result) +{ + switch (eval) + { + case E_PixelPres_Color: + result = "COLOR"; + break; + case E_PixelPres_Monochrome: + result = "MONOCHROME"; + break; + case E_PixelPres_Mixed: + result = "MIXED"; + break; + case E_PixelPres_TrueColor: + result = "TRUE COLOR"; + break; + case E_PixelPres_Empty: + result = ""; + break; + case E_PixelPres_Invalid: + result = ""; + return OFFalse; + default: + result = ""; + DCMFG_WARN("Unknown value for enum FGCTImageFrameType::E_PixelPresentation: " << eval); + return OFFalse; + } + return OFTrue; +} + +FGCTImageFrameType::E_VolumetricProperties FGCTImageFrameType::volProps2Enum(const OFString& str) +{ + if (str == "DISTORTED") + return E_VolProp_Distorted; + else if (str == "MIXED") + return E_VolProp_Mixed; + else if (str == "SAMPLED") + return E_VolProp_Sampled; + else if (str == "VOLUME") + return E_VolProp_Volume; + else if (str.empty()) + return E_VolProp_Empty; + else + return E_VolProp_Invalid; +} + +OFBool FGCTImageFrameType::volProps2Str(const FGCTImageFrameType::E_VolumetricProperties& eval, OFString& result) +{ + switch (eval) + { + case E_VolProp_Distorted: + result = "DISTORTED"; + break; + case E_VolProp_Mixed: + result = "MIXED"; + break; + case E_VolProp_Sampled: + result = "SAMPLED"; + break; + case E_VolProp_Volume: + result = "VOLUME"; + break; + case E_VolProp_Empty: + result = ""; + break; + case E_VolProp_Invalid: + result = ""; + return OFFalse; + default: + result = ""; + DCMFG_WARN("Unknown value for enum FGCTImageFrameType::E_VolumetricProperties: " << eval); + return OFFalse; + } + return OFTrue; +} diff --git a/dcmfg/libsrc/fgctposition.cc b/dcmfg/libsrc/fgctposition.cc new file mode 100644 index 00000000..c038d6c5 --- /dev/null +++ b/dcmfg/libsrc/fgctposition.cc @@ -0,0 +1,168 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Position Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctposition.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTPosition::FGCTPosition() + : FGBase(DcmFGTypes::EFG_CTPOSITION) + , m_TablePosition(DCM_TablePosition) + , m_DataCollectionCenterPatient(DCM_DataCollectionCenterPatient) + , m_ReconstructionTargetCenterPatient(DCM_ReconstructionTargetCenterPatient) +{ +} + +FGCTPosition::~FGCTPosition() +{ + // nothing to do +} + +FGBase* FGCTPosition::clone() const +{ + FGCTPosition* copy = new FGCTPosition(); + if (copy) + { + copy->m_TablePosition = this->m_TablePosition; + copy->m_DataCollectionCenterPatient = this->m_DataCollectionCenterPatient; + copy->m_ReconstructionTargetCenterPatient = this->m_ReconstructionTargetCenterPatient; + } + return copy; +} + +void FGCTPosition::clearData() +{ + m_TablePosition.clear(); + m_DataCollectionCenterPatient.clear(); + m_ReconstructionTargetCenterPatient.clear(); +} + +OFCondition FGCTPosition::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Position Sequence from given item +OFCondition FGCTPosition::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_CTPositionSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TablePosition, "1", "1C", "CTPositionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DataCollectionCenterPatient, "3", "1C", "CTPositionMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_ReconstructionTargetCenterPatient, "3", "1C", "CTPositionMacro"); + return EC_Normal; +} + +/// Writes single CT Position Sequence into given item +OFCondition FGCTPosition::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_CTPositionSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_TablePosition, "1", "1C", "CTPositionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_DataCollectionCenterPatient, "3", "1C", "CTPositionMacro"); + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_ReconstructionTargetCenterPatient, "3", "1C", "CTPositionMacro"); + return result; +} + +int FGCTPosition::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTPosition* myRhs = OFstatic_cast(const FGCTPosition*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_TablePosition.compare(myRhs->m_TablePosition); + if (result == 0) + result = m_DataCollectionCenterPatient.compare(myRhs->m_DataCollectionCenterPatient); + if (result == 0) + result = m_ReconstructionTargetCenterPatient.compare(myRhs->m_ReconstructionTargetCenterPatient); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTPosition::getTablePosition(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_TablePosition, value, pos); +} + +OFCondition FGCTPosition::getTablePosition(Float64& value, const unsigned long pos) +{ + return m_TablePosition.getFloat64(value, pos); +} + +OFCondition FGCTPosition::getDataCollectionCenterPatient(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_DataCollectionCenterPatient, value, pos); +} + +OFCondition FGCTPosition::getDataCollectionCenterPatient(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_DataCollectionCenterPatient, values); +} + +OFCondition FGCTPosition::getReconstructionTargetCenterPatient(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionTargetCenterPatient, value, pos); +} + +OFCondition FGCTPosition::getReconstructionTargetCenterPatient(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_ReconstructionTargetCenterPatient, values); +} + +// --- set() functionality --- + +OFCondition FGCTPosition::setTablePosition(const Float64 value, const OFBool checkValue) +{ + return m_TablePosition.putFloat64(value); +} + +OFCondition FGCTPosition::setDataCollectionCenterPatient(const OFVector& values, const OFBool checkValue) +{ + return DcmIODUtil::setFloat64ValuesOnElement(m_DataCollectionCenterPatient, values, "3", checkValue); +} + +OFCondition FGCTPosition::setReconstructionTargetCenterPatient(const OFVector& values, const OFBool checkValue) +{ + return DcmIODUtil::setFloat64ValuesOnElement(m_ReconstructionTargetCenterPatient, values, "3", checkValue); +} diff --git a/dcmfg/libsrc/fgctreconstruction.cc b/dcmfg/libsrc/fgctreconstruction.cc new file mode 100644 index 00000000..fd292f41 --- /dev/null +++ b/dcmfg/libsrc/fgctreconstruction.cc @@ -0,0 +1,285 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Reconstruction Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctreconstruction.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTReconstruction::FGCTReconstruction() + : FGBase(DcmFGTypes::EFG_CTRECONSTRUCTION) + , m_ReconstructionAlgorithm(DCM_ReconstructionAlgorithm) + , m_ConvolutionKernel(DCM_ConvolutionKernel) + , m_ConvolutionKernelGroup(DCM_ConvolutionKernelGroup) + , m_ReconstructionDiameter(DCM_ReconstructionDiameter) + , m_ReconstructionFieldOfView(DCM_ReconstructionFieldOfView) + , m_ReconstructionPixelSpacing(DCM_ReconstructionPixelSpacing) + , m_ReconstructionAngle(DCM_ReconstructionAngle) + , m_ImageFilter(DCM_ImageFilter) +{ +} + +FGCTReconstruction::~FGCTReconstruction() +{ + // nothing to do +} + +FGBase* FGCTReconstruction::clone() const +{ + FGCTReconstruction* copy = new FGCTReconstruction(); + if (copy) + { + copy->m_ReconstructionAlgorithm = this->m_ReconstructionAlgorithm; + copy->m_ConvolutionKernel = this->m_ConvolutionKernel; + copy->m_ConvolutionKernelGroup = this->m_ConvolutionKernelGroup; + copy->m_ReconstructionDiameter = this->m_ReconstructionDiameter; + copy->m_ReconstructionFieldOfView = this->m_ReconstructionFieldOfView; + copy->m_ReconstructionPixelSpacing = this->m_ReconstructionPixelSpacing; + copy->m_ReconstructionAngle = this->m_ReconstructionAngle; + copy->m_ImageFilter = this->m_ImageFilter; + } + return copy; +} + +void FGCTReconstruction::clearData() +{ + m_ReconstructionAlgorithm.clear(); + m_ConvolutionKernel.clear(); + m_ConvolutionKernelGroup.clear(); + m_ReconstructionDiameter.clear(); + m_ReconstructionFieldOfView.clear(); + m_ReconstructionPixelSpacing.clear(); + m_ReconstructionAngle.clear(); + m_ImageFilter.clear(); +} + +OFCondition FGCTReconstruction::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Reconstruction Sequence from given item +OFCondition FGCTReconstruction::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_CTReconstructionSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ReconstructionAlgorithm, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ConvolutionKernel, "1-n", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ConvolutionKernelGroup, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ReconstructionDiameter, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_ReconstructionFieldOfView, "2", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_ReconstructionPixelSpacing, "2", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ReconstructionAngle, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageFilter, "1", "1C", "CTReconstructionMacro"); + + return EC_Normal; +} + +/// Writes single CT Reconstruction Sequence into given item +OFCondition FGCTReconstruction::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_CTReconstructionSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ReconstructionAlgorithm, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ConvolutionKernel, "1-n", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ConvolutionKernelGroup, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ReconstructionDiameter, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ReconstructionFieldOfView, "2", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_ReconstructionPixelSpacing, "2", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ReconstructionAngle, "1", "1C", "CTReconstructionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageFilter, "1", "1C", "CTReconstructionMacro"); + + return result; +} + +int FGCTReconstruction::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTReconstruction* myRhs = OFstatic_cast(const FGCTReconstruction*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_ReconstructionAlgorithm.compare(myRhs->m_ReconstructionAlgorithm); + if (result == 0) + result = m_ConvolutionKernel.compare(myRhs->m_ConvolutionKernel); + if (result == 0) + result = m_ConvolutionKernelGroup.compare(myRhs->m_ConvolutionKernelGroup); + if (result == 0) + result = m_ReconstructionDiameter.compare(myRhs->m_ReconstructionDiameter); + if (result == 0) + result = m_ReconstructionFieldOfView.compare(myRhs->m_ReconstructionFieldOfView); + if (result == 0) + result = m_ReconstructionPixelSpacing.compare(myRhs->m_ReconstructionPixelSpacing); + if (result == 0) + result = m_ReconstructionAngle.compare(myRhs->m_ReconstructionAngle); + if (result == 0) + result = m_ImageFilter.compare(myRhs->m_ImageFilter); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTReconstruction::getReconstructionAlgorithm(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionAlgorithm, value, pos); +} + +OFCondition FGCTReconstruction::getConvolutionKernel(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ConvolutionKernel, value, pos); +} + +OFCondition FGCTReconstruction::getConvolutionKernelGroup(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ConvolutionKernelGroup, value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionDiameter(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionDiameter, value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionDiameter(Float64& value, const unsigned long pos) +{ + return m_ReconstructionDiameter.getFloat64(value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionFieldOfView(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionFieldOfView, value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionFieldOfView(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_ReconstructionFieldOfView, values); +} + +OFCondition FGCTReconstruction::getReconstructionPixelSpacing(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionPixelSpacing, value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionPixelSpacing(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_ReconstructionPixelSpacing, values); +} + +OFCondition FGCTReconstruction::getReconstructionAngle(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReconstructionAngle, value, pos); +} + +OFCondition FGCTReconstruction::getReconstructionAngle(Float64& value, const unsigned long pos) +{ + return m_ReconstructionAngle.getFloat64(value, pos); +} + +OFCondition FGCTReconstruction::getImageFilter(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ImageFilter, value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTReconstruction::setReconstructionAlgorithm(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ReconstructionAlgorithm.putString(value.c_str()); + return result; +} + +OFCondition FGCTReconstruction::setConvolutionKernel(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_ConvolutionKernel.putString(value.c_str()); + return result; +} + +OFCondition FGCTReconstruction::setConvolutionKernelGroup(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ConvolutionKernelGroup.putString(value.c_str()); + return result; +} + +OFCondition FGCTReconstruction::setReconstructionDiameter(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_ReconstructionDiameter.putFloat64(value); +} + +OFCondition +FGCTReconstruction::setReconstructionFieldOfView(const Float64 value1, const Float64 value2, const bool checkValue) +{ + (void)checkValue; + OFCondition result = m_ReconstructionFieldOfView.putFloat64(value1, 0); + if (result.good()) + result = m_ReconstructionFieldOfView.putFloat64(value2, 1); + return result; +} + +OFCondition +FGCTReconstruction::setReconstructionPixelSpacing(const Float64 value1, const Float64 value2, const bool checkValue) +{ + (void)checkValue; + OFCondition result = m_ReconstructionPixelSpacing.putFloat64(value1, 0); + if (result.good()) + result = m_ReconstructionPixelSpacing.putFloat64(value2, 1); + return result; +} + +OFCondition FGCTReconstruction::setReconstructionAngle(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_ReconstructionAngle.putFloat64(value); +} + +OFCondition FGCTReconstruction::setImageFilter(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ImageFilter.putString(value.c_str()); + return result; +} diff --git a/dcmfg/libsrc/fgcttabledynamics.cc b/dcmfg/libsrc/fgcttabledynamics.cc new file mode 100644 index 00000000..c0e17dc7 --- /dev/null +++ b/dcmfg/libsrc/fgcttabledynamics.cc @@ -0,0 +1,247 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT Table Dynamics Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgcttabledynamics.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTTableDynamics::FGCTTableDynamics() + : FGBase(DcmFGTypes::EFG_CTTABLEDYNAMICS) + , m_Items() +{ +} + +FGCTTableDynamics::~FGCTTableDynamics() +{ + clearData(); +} + +FGBase* FGCTTableDynamics::clone() const +{ + OFunique_ptr copy(new FGCTTableDynamics); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +void FGCTTableDynamics::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +OFCondition FGCTTableDynamics::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Table Dynamics Sequence from given item +OFCondition FGCTTableDynamics::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTTableDynamicsSequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTTableDynamicsSequence, num, seqItem).good()) + { + FGCTTableDynamicsItem* newItem = new FGCTTableDynamicsItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +/// Writes single CT Table Dynamics Sequence into given item +OFCondition FGCTTableDynamics::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence( + result, DCM_CTTableDynamicsSequence, m_Items, item, "1-n", "2", "CTTableDynamicsMacro"); + } + return result; +} + +int FGCTTableDynamics::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTTableDynamics* myRhs = OFstatic_cast(const FGCTTableDynamics*, &rhs); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(this->m_Items, myRhs->m_Items); +} + +OFVector& FGCTTableDynamics::getCTTableDynamicsItems() +{ + return m_Items; +} + +// -------------------------------------------------------------------------- + +// Constructor +FGCTTableDynamics::FGCTTableDynamicsItem::FGCTTableDynamicsItem() + : m_TableSpeed(DCM_TableSpeed) + , m_TableFeedPerRotation(DCM_TableFeedPerRotation) + , m_SpiralPitchFactor(DCM_SpiralPitchFactor) +{ +} + +FGCTTableDynamics::FGCTTableDynamicsItem::~FGCTTableDynamicsItem() +{ + // nothing to do +} + +FGCTTableDynamics::FGCTTableDynamicsItem* FGCTTableDynamics::FGCTTableDynamicsItem::clone() const +{ + FGCTTableDynamicsItem* copy = new FGCTTableDynamicsItem(); + if (copy) + { + copy->m_TableSpeed = this->m_TableSpeed; + copy->m_TableFeedPerRotation = this->m_TableFeedPerRotation; + copy->m_SpiralPitchFactor = this->m_SpiralPitchFactor; + } + return copy; +} + +void FGCTTableDynamics::FGCTTableDynamicsItem::clearData() +{ + m_TableSpeed.clear(); + m_TableFeedPerRotation.clear(); + m_SpiralPitchFactor.clear(); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT Table Dynamics Sequence from given item +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(item, m_TableSpeed, "1", "1C", "CTTableDynamicsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_TableFeedPerRotation, "1", "1C", "CTTableDynamicsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_SpiralPitchFactor, "1", "1C", "CTTableDynamicsMacro"); + return EC_Normal; +} + +/// Writes single CT Table Dynamics Sequence into given item +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::write(DcmItem& item) +{ + // --- write frame content macro attributes --- + OFCondition result; + DcmIODUtil::copyElementToDataset(result, item, m_TableSpeed, "1", "1C", "CTTableDynamicsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_TableFeedPerRotation, "1", "1C", "CTTableDynamicsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_SpiralPitchFactor, "1", "1C", "CTTableDynamicsMacro"); + return result; +} + +int FGCTTableDynamics::FGCTTableDynamicsItem::compare(const FGCTTableDynamics::FGCTTableDynamicsItem& rhs) const +{ + int result = 0; + const FGCTTableDynamicsItem* myRhs = OFstatic_cast(const FGCTTableDynamicsItem*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_TableSpeed.compare(myRhs->m_TableSpeed); + if (result == 0) + result = m_TableFeedPerRotation.compare(myRhs->m_TableFeedPerRotation); + if (result == 0) + result = m_SpiralPitchFactor.compare(myRhs->m_SpiralPitchFactor); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getTableSpeed(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_TableSpeed, value, pos); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getTableSpeed(Float64& value, const unsigned long pos) +{ + return m_TableSpeed.getFloat64(value, pos); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getSpiralPitchFactor(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_SpiralPitchFactor, value, pos); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getSpiralPitchFactor(Float64& value, const unsigned long pos) +{ + return m_SpiralPitchFactor.getFloat64(value, pos); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getTableFeedPerRotation(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_TableFeedPerRotation, value, pos); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::getTableFeedPerRotation(Float64& value, const unsigned long pos) +{ + return m_TableFeedPerRotation.getFloat64(value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::setTableSpeed(const Float64& value, const OFBool checkValue) +{ + return m_TableSpeed.putFloat64(value); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::setTableFeedPerRotation(const Float64& value, + const OFBool checkValue) +{ + return m_TableFeedPerRotation.putFloat64(value); +} + +OFCondition FGCTTableDynamics::FGCTTableDynamicsItem::setSpiralPitchFactor(const Float64& value, + const OFBool checkValue) +{ + return m_SpiralPitchFactor.putFloat64(value); +} diff --git a/dcmfg/libsrc/fgctxraydetails.cc b/dcmfg/libsrc/fgctxraydetails.cc new file mode 100644 index 00000000..85fd49d1 --- /dev/null +++ b/dcmfg/libsrc/fgctxraydetails.cc @@ -0,0 +1,359 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the CT X-Ray Details Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgctxraydetails.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGCTXRayDetails::FGCTXRayDetails() + : FGBase(DcmFGTypes::EFG_CTXRAYDETAILS) + , m_Items() +{ +} + +FGCTXRayDetails::~FGCTXRayDetails() +{ + DcmIODUtil::freeContainer(m_Items); +} + +FGBase* FGCTXRayDetails::clone() const +{ + OFunique_ptr copy(new FGCTXRayDetails); + if (copy) + { + if (DcmIODUtil::copyContainer(this->m_Items, copy->m_Items).good()) + { + return copy.release(); + } + } + return OFnullptr; +} + +void FGCTXRayDetails::clearData() +{ + DcmIODUtil::freeContainer(m_Items); + m_Items.clear(); +} + +OFCondition FGCTXRayDetails::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT X-Ray Details Sequence from given item +OFCondition FGCTXRayDetails::read(DcmItem& item) +{ + clearData(); + DcmItem* seqItem = NULL; + unsigned long numItems = 0; + OFCondition result = getNumItemsFromFGSequence(item, DCM_CTXRayDetailsSequence, numItems); + if (result.bad()) + return result; + + for (unsigned long num = 0; num < numItems; num++) + { + if (getItemFromFGSequence(item, DCM_CTXRayDetailsSequence, num, seqItem).good()) + { + FGCTXRayDetailsItem* newItem = new FGCTXRayDetailsItem(); + newItem->read(*seqItem); + m_Items.push_back(newItem); + } + } + return EC_Normal; +} + +/// Writes single CT X-Ray Details Sequence into given item +OFCondition FGCTXRayDetails::write(DcmItem& item) +{ + OFCondition result = check(); + if (result.good()) + { + DcmIODUtil::writeSubSequence( + result, DCM_CTXRayDetailsSequence, m_Items, item, "1-n", "2", "CTXRayDetailsMacro"); + } + return result; +} + +int FGCTXRayDetails::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGCTXRayDetails* myRhs = OFstatic_cast(const FGCTXRayDetails*, &rhs); + if (!myRhs) + return -1; + + // Compare all items + return DcmIODUtil::compareContainer(this->m_Items, myRhs->m_Items); +} + +OFVector& FGCTXRayDetails::getCTXRayDetailsItems() +{ + return m_Items; +} + +// --------------------------------------------- + +// Constructor +FGCTXRayDetails::FGCTXRayDetailsItem::FGCTXRayDetailsItem() + : m_ReferencedPathIndex(DCM_ReferencedPathIndex) + , m_KVP(DCM_KVP) + , m_FocalSpots(DCM_FocalSpots) + , m_FilterType(DCM_FilterType) + , m_FilterMaterial(DCM_FilterMaterial) + , m_CalciumScoringMassFactorPatient(DCM_CalciumScoringMassFactorPatient) + , m_CalciumScoringMassFactorDevice(DCM_CalciumScoringMassFactorDevice) + , m_EnergyWeightingFactor(DCM_EnergyWeightingFactor) +{ +} + +FGCTXRayDetails::FGCTXRayDetailsItem::~FGCTXRayDetailsItem() +{ + // nothing to do +} + +FGCTXRayDetails::FGCTXRayDetailsItem* FGCTXRayDetails::FGCTXRayDetailsItem::clone() const +{ + FGCTXRayDetailsItem* copy = new FGCTXRayDetailsItem(); + if (copy) + { + copy->m_ReferencedPathIndex = this->m_ReferencedPathIndex; + copy->m_KVP = this->m_KVP; + copy->m_FocalSpots = this->m_FocalSpots; + copy->m_FilterType = this->m_FilterType; + copy->m_FilterMaterial = this->m_FilterMaterial; + copy->m_CalciumScoringMassFactorPatient = this->m_CalciumScoringMassFactorPatient; + copy->m_CalciumScoringMassFactorDevice = this->m_CalciumScoringMassFactorDevice; + copy->m_EnergyWeightingFactor = this->m_EnergyWeightingFactor; + } + return copy; +} + +void FGCTXRayDetails::FGCTXRayDetailsItem::clearData() +{ + m_ReferencedPathIndex.clear(); + m_KVP.clear(); + m_FocalSpots.clear(); + m_FilterType.clear(); + m_FilterMaterial.clear(); + m_CalciumScoringMassFactorPatient.clear(); + m_CalciumScoringMassFactorDevice.clear(); + m_EnergyWeightingFactor.clear(); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +/// Read CT X-Ray Details Sequence from given item +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(item, m_ReferencedPathIndex, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_KVP, "1", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FocalSpots, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FilterType, "1", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_FilterMaterial, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_CalciumScoringMassFactorPatient, "1", "3", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_CalciumScoringMassFactorDevice, "3", "3", "CTXRayDetailsMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_EnergyWeightingFactor, "1", "3", "CTXRayDetailsMacro"); + return EC_Normal; +} + +/// Writes single CT X-Ray Details Sequence into given item +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::write(DcmItem& item) +{ + // --- write frame content macro attributes --- + OFCondition result; + DcmIODUtil::copyElementToDataset(result, item, m_ReferencedPathIndex, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_KVP, "1", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_FocalSpots, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_FilterType, "1", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_FilterMaterial, "1-n", "1C", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_CalciumScoringMassFactorPatient, "1", "3", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_CalciumScoringMassFactorDevice, "3", "3", "CTXRayDetailsMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_EnergyWeightingFactor, "1", "3", "CTXRayDetailsMacro"); + + return result; +} + +int FGCTXRayDetails::FGCTXRayDetailsItem::compare(const FGCTXRayDetails::FGCTXRayDetailsItem& rhs) const +{ + const FGCTXRayDetails::FGCTXRayDetailsItem* myRhs + = OFstatic_cast(const FGCTXRayDetails::FGCTXRayDetailsItem*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + int result = m_ReferencedPathIndex.compare(myRhs->m_ReferencedPathIndex); + if (result == 0) + result = m_KVP.compare(myRhs->m_KVP); + if (result == 0) + result = m_FocalSpots.compare(myRhs->m_FocalSpots); + if (result == 0) + result = m_FilterType.compare(myRhs->m_FilterType); + if (result == 0) + result = m_FilterMaterial.compare(myRhs->m_FilterMaterial); + if (result == 0) + result = m_CalciumScoringMassFactorPatient.compare(myRhs->m_CalciumScoringMassFactorPatient); + if (result == 0) + result = m_CalciumScoringMassFactorDevice.compare(myRhs->m_CalciumScoringMassFactorDevice); + if (result == 0) + result = m_EnergyWeightingFactor.compare(myRhs->m_EnergyWeightingFactor); + + return result; +} + +// --- get() functionality --- + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getReferencedPathIndex(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ReferencedPathIndex, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getReferencedPathIndex(OFVector& values) +{ + return DcmIODUtil::getUint16ValuesFromElement(m_ReferencedPathIndex, values); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getKVP(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_KVP, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getKVP(Float64& value, const unsigned long pos) +{ + return m_KVP.getFloat64(value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getFocalSpots(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FocalSpots, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getFocalSpots(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_FocalSpots, values); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getFilterType(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FilterType, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getFilterMaterial(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FilterType, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getCalciumScoringMassFactorPatient(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_CalciumScoringMassFactorPatient, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getCalciumScoringMassFactorPatient(Float32& value, + const unsigned long pos) +{ + return m_CalciumScoringMassFactorPatient.getFloat32(value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getCalciumScoringMassFactorDevice(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_CalciumScoringMassFactorDevice, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getCalciumScoringMassFactorDevice(OFVector& values) +{ + return DcmIODUtil::getFloat64ValuesFromElement(m_CalciumScoringMassFactorDevice, values); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getEnergyWeightingFactor(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_EnergyWeightingFactor, value, pos); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::getEnergyWeightingFactor(Float32& value, const unsigned long pos) +{ + return m_EnergyWeightingFactor.getFloat32(value, pos); +} + +// --- set() functionality --- + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setReferencedPathIndex(const OFVector& values, + const bool checkValues) +{ + (void)checkValues; + return DcmIODUtil::setUint16ValuesOnElement(m_ReferencedPathIndex, values, "1-n", checkValues); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setKVP(const Float64 value, const bool checkValue) +{ + (void)checkValue; + return m_KVP.putFloat64(value); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setFocalSpots(const OFVector& values, const bool checkValues) +{ + return DcmIODUtil::setFloat64ValuesOnElement(m_FocalSpots, values, "1-n", checkValues); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setFilterType(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FilterType.putString(value.c_str()); + return result; +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setFilterMaterial(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_FilterMaterial.putString(value.c_str()); + return result; +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setCalciumScoringMassFactorPatient(const Float32 value, + const bool checkValue) +{ + return m_CalciumScoringMassFactorPatient.putFloat32(value); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setCalciumScoringMassFactorDevice(const OFVector& values, + const bool checkValues) +{ + return DcmIODUtil::setFloat32ValuesOnElement(m_CalciumScoringMassFactorDevice, values, "1-n", checkValues); +} + +OFCondition FGCTXRayDetails::FGCTXRayDetailsItem::setEnergyWeightingFactor(const Float32 value, const bool checkValue) +{ + return m_EnergyWeightingFactor.putFloat32(value); +} diff --git a/dcmfg/libsrc/fgderimg.cc b/dcmfg/libsrc/fgderimg.cc index d6874474..f36e9c96 100644 --- a/dcmfg/libsrc/fgderimg.cc +++ b/dcmfg/libsrc/fgderimg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,694 +19,620 @@ * */ - #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmdata/dcitem.h" + #include "dcmtk/dcmdata/dcdatutl.h" +#include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmfg/fgderimg.h" #include "dcmtk/dcmiod/iodutil.h" - -FGDerivationImage::FGDerivationImage() : - FGBase(DcmFGTypes::EFG_DERIVATIONIMAGE), - m_DerivationImageItems() +FGDerivationImage::FGDerivationImage() + : FGBase(DcmFGTypes::EFG_DERIVATIONIMAGE) + , m_DerivationImageItems() { } - FGDerivationImage::~FGDerivationImage() { - DcmIODUtil::freeContainer(m_DerivationImageItems); + DcmIODUtil::freeContainer(m_DerivationImageItems); } - FGBase* FGDerivationImage::clone() const { - FGDerivationImage* copy = new FGDerivationImage(); - if (copy) - { - OFVector::const_iterator it = m_DerivationImageItems.begin(); - while ( it != m_DerivationImageItems.end() ) + OFunique_ptr copy(new FGDerivationImage); + if (copy) { - DerivationImageItem* itemCopy = new DerivationImageItem(); - if (!itemCopy) - { - DCMFG_FATAL("Cannot clone FGDerivationImage: Memory exhausted"); - return NULL; - } - *itemCopy = **it; - copy->getDerivationImageItems().push_back(itemCopy); - it++; + if (DcmIODUtil::copyContainer(this->m_DerivationImageItems, copy->m_DerivationImageItems).good()) + { + return copy.release(); + } } - } - return copy; + return OFnullptr; } - FGDerivationImage* FGDerivationImage::createMinimal(const OFVector& derivationImages, const OFString& derivationDescription, const CodeSequenceMacro& derivationCode, const CodeSequenceMacro& purposeOfReference) { - OFCondition result; - FGDerivationImage* group = new FGDerivationImage(); - if (group) - { - DerivationImageItem* derivItem = NULL; - result = group->addDerivationImageItem(derivationCode, derivationDescription, derivItem); - if (result.good()) + OFCondition result; + FGDerivationImage* group = new FGDerivationImage(); + if (group) { - OFVector srcImages = derivItem->getSourceImageItems(); - OFVector::const_iterator imageRef = derivationImages.begin(); - while (imageRef != derivationImages.end()) - { - SourceImageItem* item = new SourceImageItem(); - if (item) + DerivationImageItem* derivItem = NULL; + result = group->addDerivationImageItem(derivationCode, derivationDescription, derivItem); + if (result.good()) { - item->getPurposeOfReferenceCode() = purposeOfReference; - item->getImageSOPInstanceReference() = *imageRef; - derivItem->getSourceImageItems().push_back(item); + OFVector srcImages = derivItem->getSourceImageItems(); + OFVector::const_iterator imageRef = derivationImages.begin(); + while (imageRef != derivationImages.end()) + { + SourceImageItem* item = new SourceImageItem(); + if (item) + { + item->getPurposeOfReferenceCode() = purposeOfReference; + item->getImageSOPInstanceReference() = *imageRef; + derivItem->getSourceImageItems().push_back(item); + } + else + { + DCMFG_ERROR("Cannot create derivation description: Out of memory"); + result = EC_MemoryExhausted; + } + imageRef++; + } } else { - DCMFG_ERROR("Cannot create derivation description: Out of memory"); - result = EC_MemoryExhausted; + DCMFG_ERROR("Cannot create derivation description: " << result.text()); } - imageRef++; - } } else { - DCMFG_ERROR("Cannot create derivation description: " << result.text()); + result = EC_MemoryExhausted; } - } - else - { - result = EC_MemoryExhausted; - } - if (result.bad()) - { - delete group; - group = NULL; - } + if (result.bad()) + { + delete group; + group = NULL; + } - return group; + return group; } - int FGDerivationImage::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGDerivationImage* myRhs = OFstatic_cast(const FGDerivationImage*, &rhs); - if (!myRhs) - { - return -1; - } - - size_t thisSize = m_DerivationImageItems.size(); - size_t rhsSize = myRhs->m_DerivationImageItems.size(); - if (thisSize < rhsSize) - { - return 1; - } - else if (thisSize > rhsSize) - { - return -1; - } + const FGDerivationImage* myRhs = OFstatic_cast(const FGDerivationImage*, &rhs); + if (!myRhs) + { + return -1; + } - for (size_t count = 0; count < thisSize; count++) - { - int error = (*(m_DerivationImageItems[count])).compare( (*(myRhs->m_DerivationImageItems[count])) ); - if (error != 0) + size_t thisSize = m_DerivationImageItems.size(); + size_t rhsSize = myRhs->m_DerivationImageItems.size(); + if (thisSize < rhsSize) + { + return 1; + } + else if (thisSize > rhsSize) { - return error; + return -1; } - } - return 0; + for (size_t count = 0; count < thisSize; count++) + { + int error = (*(m_DerivationImageItems[count])).compare((*(myRhs->m_DerivationImageItems[count]))); + if (error != 0) + { + return error; + } + } + return 0; } - void FGDerivationImage::clearData() { - DcmIODUtil::freeContainer(m_DerivationImageItems); + DcmIODUtil::freeContainer(m_DerivationImageItems); } - OFCondition FGDerivationImage::check() const { - OFCondition result; - OFVector::const_iterator it = m_DerivationImageItems.begin(); - while ( (it != m_DerivationImageItems.end()) && result.good() ) - { - result = (*it)->check(); - it++; - } + OFCondition result; + OFVector::const_iterator it = m_DerivationImageItems.begin(); + while ((it != m_DerivationImageItems.end()) && result.good()) + { + result = (*it)->check(); + it++; + } - return result; + return result; } DerivationImageItem& DerivationImageItem::operator=(const DerivationImageItem& rhs) { - m_DerivationDescription = rhs.m_DerivationDescription; - // Copy nested structures: Derivation Codes - OFVector::const_iterator code = rhs.m_DerivationCodeItems.begin(); - while ( code != rhs.m_DerivationCodeItems.end() ) - { - m_DerivationCodeItems.push_back(new CodeSequenceMacro(**code)); - code++; - } - // Copy nested structures: Derivation Codes - OFVector::const_iterator source = rhs.m_SourceImageItems.begin(); - while ( source != rhs.m_SourceImageItems.end() ) - { - m_SourceImageItems.push_back(new SourceImageItem(**source)); - source++; - } - return *this; + m_DerivationDescription = rhs.m_DerivationDescription; + // Copy nested structures: Derivation Codes + OFVector::const_iterator code = rhs.m_DerivationCodeItems.begin(); + while (code != rhs.m_DerivationCodeItems.end()) + { + m_DerivationCodeItems.push_back(new CodeSequenceMacro(**code)); + code++; + } + // Copy nested structures: Derivation Codes + OFVector::const_iterator source = rhs.m_SourceImageItems.begin(); + while (source != rhs.m_SourceImageItems.end()) + { + m_SourceImageItems.push_back(new SourceImageItem(**source)); + source++; + } + return *this; } - OFCondition FGDerivationImage::addDerivationImageItem(const CodeSequenceMacro& derivationCode, const OFString& derivationDescription, DerivationImageItem*& item) { - OFCondition result; - item = new DerivationImageItem(); - if (item == NULL) - { - return EC_MemoryExhausted; - } - - // Initialize with given data - if (result.good()) - { - result = item->setDerivationDescription(derivationDescription); - } - if (result.good()) - { - item->getDerivationCodeItems().push_back(new CodeSequenceMacro(derivationCode)); - m_DerivationImageItems.push_back(item); - } - else - { - delete item; - item = NULL; - result = FG_EC_InvalidData; - } - return result; -} + OFCondition result; + item = new DerivationImageItem(); + if (item == NULL) + { + return EC_MemoryExhausted; + } + // Initialize with given data + if (result.good()) + { + result = item->setDerivationDescription(derivationDescription); + } + if (result.good()) + { + item->getDerivationCodeItems().push_back(new CodeSequenceMacro(derivationCode)); + m_DerivationImageItems.push_back(item); + } + else + { + delete item; + item = NULL; + result = FG_EC_InvalidData; + } + return result; +} OFVector& FGDerivationImage::getDerivationImageItems() { - return m_DerivationImageItems; + return m_DerivationImageItems; } - OFCondition FGDerivationImage::read(DcmItem& item) { - /* re-initialize object */ - clearData(); + /* re-initialize object */ + clearData(); - DcmSequenceOfItems *derivationImageSequence = NULL; - if (item.findAndGetSequence(DCM_DerivationImageSequence, derivationImageSequence).bad()) - return FG_EC_NoSuchGroup; + DcmSequenceOfItems* derivationImageSequence = NULL; + if (item.findAndGetSequence(DCM_DerivationImageSequence, derivationImageSequence).bad()) + return FG_EC_NoSuchGroup; - /* Read Derivation Image Sequence */ - DcmIODUtil::readSubSequence > - ( derivationImageSequence, - DCM_DerivationImageSequence, - m_DerivationImageItems, - "0-n", - "2", - "DerivationImageMacro"); + /* Read Derivation Image Sequence */ + DcmIODUtil::readSubSequence >(derivationImageSequence, + DCM_DerivationImageSequence, + m_DerivationImageItems, + "0-n", + "2", + "DerivationImageMacro"); - return EC_Normal; + return EC_Normal; } - OFCondition FGDerivationImage::write(DcmItem& item) { - OFCondition result = check(); - DcmIODUtil::writeSubSequence > - ( result, - DCM_DerivationImageSequence, - m_DerivationImageItems, - item, - "0-n", - "2", - "DerivationImageMacro" ); - return result; + OFCondition result = check(); + DcmIODUtil::writeSubSequence >( + result, DCM_DerivationImageSequence, m_DerivationImageItems, item, "0-n", "2", "DerivationImageMacro"); + return result; } - /* -- Class SourceImage Implementation -- */ SourceImageItem::SourceImageItem() - : m_PurposeOfReferenceCode(), - m_ImageSOPInstanceReference() + : m_PurposeOfReferenceCode() + , m_ImageSOPInstanceReference() { } - SourceImageItem::~SourceImageItem() { - clearData(); + clearData(); } - SourceImageItem& SourceImageItem::operator=(const SourceImageItem& rhs) { - m_PurposeOfReferenceCode = rhs.m_PurposeOfReferenceCode; - m_ImageSOPInstanceReference = rhs.m_ImageSOPInstanceReference; - return *this; + m_PurposeOfReferenceCode = rhs.m_PurposeOfReferenceCode; + m_ImageSOPInstanceReference = rhs.m_ImageSOPInstanceReference; + return *this; } - void SourceImageItem::clearData() { - m_PurposeOfReferenceCode.clearData(); - m_ImageSOPInstanceReference.clear(); + m_PurposeOfReferenceCode.clearData(); + m_ImageSOPInstanceReference.clear(); } - OFCondition SourceImageItem::check() const { - OFCondition result = OFconst_cast(ImageSOPInstanceReferenceMacro*, &m_ImageSOPInstanceReference)->check(); - if (result.bad()) - { - return result; - } + OFCondition result = OFconst_cast(ImageSOPInstanceReferenceMacro*, &m_ImageSOPInstanceReference)->check(); + if (result.bad()) + { + return result; + } - return OFconst_cast(CodeSequenceMacro*, &m_PurposeOfReferenceCode)->check(); + return OFconst_cast(CodeSequenceMacro*, &m_PurposeOfReferenceCode)->check(); } - int SourceImageItem::compare(const SourceImageItem& rhs) const { - int result = this->m_PurposeOfReferenceCode.compare(rhs.m_PurposeOfReferenceCode); - if (result != 0) - { - result = this->m_ImageSOPInstanceReference.compare(rhs.m_ImageSOPInstanceReference); - } + int result = this->m_PurposeOfReferenceCode.compare(rhs.m_PurposeOfReferenceCode); + if (result != 0) + { + result = this->m_ImageSOPInstanceReference.compare(rhs.m_ImageSOPInstanceReference); + } - return result; + return result; } - CodeSequenceMacro& SourceImageItem::getPurposeOfReferenceCode() { - return m_PurposeOfReferenceCode; + return m_PurposeOfReferenceCode; } - ImageSOPInstanceReferenceMacro& SourceImageItem::getImageSOPInstanceReference() { - return m_ImageSOPInstanceReference; + return m_ImageSOPInstanceReference; } - -OFCondition SourceImageItem::read(DcmItem& itemOfSourceImageSequence, - const OFBool clearOldData) +OFCondition SourceImageItem::read(DcmItem& itemOfSourceImageSequence, const OFBool clearOldData) { - /* Re-initialize object */ - if (clearOldData) - clearData(); + /* Re-initialize object */ + if (clearOldData) + clearData(); - /* Read Purpose of Reference Code Sequence */ - DcmIODUtil::readSingleItem(itemOfSourceImageSequence, DCM_PurposeOfReferenceCodeSequence, m_PurposeOfReferenceCode, "1", "DerivationImageMacro"); + /* Read Purpose of Reference Code Sequence */ + DcmIODUtil::readSingleItem(itemOfSourceImageSequence, + DCM_PurposeOfReferenceCodeSequence, + m_PurposeOfReferenceCode, + "1", + "DerivationImageMacro"); - /* Read Source Image Sequence */ - m_ImageSOPInstanceReference.read(itemOfSourceImageSequence); + /* Read Source Image Sequence */ + m_ImageSOPInstanceReference.read(itemOfSourceImageSequence); - return EC_Normal; + return EC_Normal; } - OFCondition SourceImageItem::write(DcmItem& itemOfSourceImageSequence) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - /* Write Purpose of Reference Code Sequence */ - DcmIODUtil::writeSingleItem(result, DCM_PurposeOfReferenceCodeSequence, m_PurposeOfReferenceCode, itemOfSourceImageSequence, "1", "DerivationImageMacro"); + /* Write Purpose of Reference Code Sequence */ + DcmIODUtil::writeSingleItem(result, + DCM_PurposeOfReferenceCodeSequence, + m_PurposeOfReferenceCode, + itemOfSourceImageSequence, + "1", + "DerivationImageMacro"); - /* Write Image SOP Instance Reference Macro */ - if ( result.good() ) - { - m_ImageSOPInstanceReference.write(itemOfSourceImageSequence); - } + /* Write Image SOP Instance Reference Macro */ + if (result.good()) + { + m_ImageSOPInstanceReference.write(itemOfSourceImageSequence); + } - return result; + return result; } - /* -- Class DerivationImageItem Implementation -- */ DerivationImageItem::DerivationImageItem() - : m_DerivationDescription(DCM_DerivationDescription), - m_DerivationCodeItems(), - m_SourceImageItems() + : m_DerivationDescription(DCM_DerivationDescription) + , m_DerivationCodeItems() + , m_SourceImageItems() { } - DerivationImageItem::DerivationImageItem(const DerivationImageItem& rhs) - : m_DerivationDescription(rhs.m_DerivationDescription), - m_DerivationCodeItems(), - m_SourceImageItems() + : m_DerivationDescription(rhs.m_DerivationDescription) + , m_DerivationCodeItems() + , m_SourceImageItems() { - OFVector::const_iterator it = rhs.m_DerivationCodeItems.begin(); - while (it != rhs.m_DerivationCodeItems.end()) - { - CodeSequenceMacro* copy = new CodeSequenceMacro(**it); - if (!copy) - { - DCMFG_ERROR("Could not create copy of DerivationImageItem: Memory exhausted"); - this->clearData(); - return; - } - m_DerivationCodeItems.push_back(copy); - it++; - } - - OFVector::const_iterator src = rhs.m_SourceImageItems.begin(); - while (src != rhs.m_SourceImageItems.end()) - { - SourceImageItem* copy = new SourceImageItem(**src); - if (!copy) - { - DCMFG_ERROR("Could not create copy of DerivationImageItem: Memory exhausted"); - this->clearData(); - return; - } - m_SourceImageItems.push_back(copy); - it++; - } + DcmIODUtil::copyContainer(rhs.m_DerivationCodeItems, this->m_DerivationCodeItems); + DcmIODUtil::copyContainer(rhs.m_SourceImageItems, this->m_SourceImageItems); } - void DerivationImageItem::clearData() { - m_DerivationDescription.clear(); - DcmIODUtil::freeContainer(m_DerivationCodeItems); - DcmIODUtil::freeContainer(m_SourceImageItems); + m_DerivationDescription.clear(); + DcmIODUtil::freeContainer(m_DerivationCodeItems); + DcmIODUtil::freeContainer(m_SourceImageItems); } - int DerivationImageItem::compare(const DerivationImageItem& rhs) const { - if (this == &rhs) - return OFTrue; - - int result = m_DerivationDescription.compare(rhs.m_DerivationDescription); - if (result != 0) return result; - - size_t numThis = m_DerivationCodeItems.size(); - size_t numRhs = rhs.m_DerivationCodeItems.size(); - size_t maxSize = (numThis > numRhs) ? numThis : numRhs; - for (size_t count = 0; count < maxSize; count++) - { - int error = (*m_DerivationCodeItems[count]).compare(*(rhs.m_DerivationCodeItems[count])); - if (error != 0) - { - return error; - } - } - if (numThis < numRhs) - { - return 1; - } - else if (numThis > numRhs) - { - return -1; - } - - numThis = m_SourceImageItems.size(); - numRhs = rhs.m_SourceImageItems.size(); - maxSize = (numThis > numRhs) ? numThis : numRhs; - for (size_t count = 0; count < maxSize; count++) - { - int error = (*m_SourceImageItems[count]).compare(*(rhs.m_SourceImageItems[count])); - if (error != 0) - { - return error; - } - } - if (numThis < numRhs) - { - return 1; - } - else if (numThis > numRhs) - { - return -1; - } - - // If we get here, the object values must be identical - return 0; -} + if (this == &rhs) + return OFTrue; + + int result = m_DerivationDescription.compare(rhs.m_DerivationDescription); + if (result != 0) + return result; + + size_t numThis = m_DerivationCodeItems.size(); + size_t numRhs = rhs.m_DerivationCodeItems.size(); + size_t maxSize = (numThis > numRhs) ? numThis : numRhs; + for (size_t count = 0; count < maxSize; count++) + { + int error = (*m_DerivationCodeItems[count]).compare(*(rhs.m_DerivationCodeItems[count])); + if (error != 0) + { + return error; + } + } + if (numThis < numRhs) + { + return 1; + } + else if (numThis > numRhs) + { + return -1; + } + numThis = m_SourceImageItems.size(); + numRhs = rhs.m_SourceImageItems.size(); + maxSize = (numThis > numRhs) ? numThis : numRhs; + for (size_t count = 0; count < maxSize; count++) + { + int error = (*m_SourceImageItems[count]).compare(*(rhs.m_SourceImageItems[count])); + if (error != 0) + { + return error; + } + } + if (numThis < numRhs) + { + return 1; + } + else if (numThis > numRhs) + { + return -1; + } + + // If we get here, the object values must be identical + return 0; +} OFCondition DerivationImageItem::check() const { - if (m_DerivationCodeItems.size() == 0) - { - DCMFG_ERROR("Derivation Code Sequence in Derivation Image Functional Group Macro must have one or more items"); - return FG_EC_InvalidData; - } + if (m_DerivationCodeItems.size() == 0) + { + DCMFG_ERROR("Derivation Code Sequence in Derivation Image Functional Group Macro must have one or more items"); + return FG_EC_InvalidData; + } - OFCondition result; - OFVector::const_iterator it = m_DerivationCodeItems.begin(); - while (it != m_DerivationCodeItems.end() && result.good()) - { - result = (*it)->check(); - it++; - } + OFCondition result; + OFVector::const_iterator it = m_DerivationCodeItems.begin(); + while (it != m_DerivationCodeItems.end() && result.good()) + { + result = (*it)->check(); + it++; + } - OFVector::const_iterator ref = m_SourceImageItems.begin(); - while ((ref != m_SourceImageItems.end()) && result.good()) - { - result = (*ref)->check(); - ref++; - } - return result; + OFVector::const_iterator ref = m_SourceImageItems.begin(); + while ((ref != m_SourceImageItems.end()) && result.good()) + { + result = (*ref)->check(); + ref++; + } + return result; } - DerivationImageItem::~DerivationImageItem() { - clearData(); + clearData(); } - OFCondition DerivationImageItem::addSourceImageItem(const OFString& file, const CodeSequenceMacro& purposeOfReference, SourceImageItem*& resultSourceImageItem) { - DcmFileFormat dcmff; - DcmDataset *dataset = NULL; - OFCondition result = dcmff.loadFile(file.c_str()); - if (result.bad()) - { - DCMFG_ERROR("Could not load file " << file << ": " << result.text()); - return result; - } - dataset = dcmff.getDataset(); - return addSourceImageItem(dataset, purposeOfReference, resultSourceImageItem); + DcmFileFormat dcmff; + DcmDataset* dataset = NULL; + OFCondition result = dcmff.loadFile(file.c_str()); + if (result.bad()) + { + DCMFG_ERROR("Could not load file " << file << ": " << result.text()); + return result; + } + dataset = dcmff.getDataset(); + return addSourceImageItem(dataset, purposeOfReference, resultSourceImageItem); } - -OFCondition DerivationImageItem::addSourceImageItem(DcmDataset *dataset, +OFCondition DerivationImageItem::addSourceImageItem(DcmDataset* dataset, const CodeSequenceMacro& purposeOfReference, SourceImageItem*& resultSourceImageItem) { - // Create new source image item - SourceImageItem *item = new SourceImageItem(); - if (item == NULL) - { - return EC_MemoryExhausted; - } - - // check code validity - if ( OFconst_cast(CodeSequenceMacro*, &purposeOfReference)->check().bad() ) - { - DCMFG_ERROR("Purpose of Reference code within item of Derivation Image Sequence is invalid"); - return FG_EC_InvalidData; - } - - item->getPurposeOfReferenceCode() = purposeOfReference; - resultSourceImageItem = NULL; - OFString sopClass, sopInstance, ts; - OFCondition result = DcmDataUtil::getSOPInstanceFromDataset(dataset, EXS_Unknown, sopClass, sopInstance, ts /*ignored*/); - { - if ( result.good() ) result = item->getImageSOPInstanceReference().setReferencedSOPClassUID(sopClass); - if ( result.good() ) result = item->getImageSOPInstanceReference().setReferencedSOPInstanceUID(sopInstance); - } - if (result.good()) - { - m_SourceImageItems.push_back(item); - resultSourceImageItem = item; - } - else - { - delete item; - } - - return result; -} - - -OFCondition DerivationImageItem::addSourceImageItems(const OFVector< OFString >& files, + // Create new source image item + SourceImageItem* item = new SourceImageItem(); + if (item == NULL) + { + return EC_MemoryExhausted; + } + + // check code validity + if (OFconst_cast(CodeSequenceMacro*, &purposeOfReference)->check().bad()) + { + DCMFG_ERROR("Purpose of Reference code within item of Derivation Image Sequence is invalid"); + return FG_EC_InvalidData; + } + + item->getPurposeOfReferenceCode() = purposeOfReference; + resultSourceImageItem = NULL; + OFString sopClass, sopInstance, ts; + OFCondition result + = DcmDataUtil::getSOPInstanceFromDataset(dataset, EXS_Unknown, sopClass, sopInstance, ts /*ignored*/); + { + if (result.good()) + result = item->getImageSOPInstanceReference().setReferencedSOPClassUID(sopClass); + if (result.good()) + result = item->getImageSOPInstanceReference().setReferencedSOPInstanceUID(sopInstance); + } + if (result.good()) + { + m_SourceImageItems.push_back(item); + resultSourceImageItem = item; + } + else + { + delete item; + } + + return result; +} + +OFCondition DerivationImageItem::addSourceImageItems(const OFVector& files, const CodeSequenceMacro& purposeOfReference, OFVector& resultSourceImageItems, const OFBool skipErrors) { - DcmFileFormat dcmff; - OFCondition result; - DcmDataset *dataset = NULL; - OFVector datasets; - OFVector::const_iterator it = files.begin(); - while (it != files.end()) - { - result = dcmff.loadFile((*it).c_str()); - if (result.bad()) + DcmFileFormat dcmff; + OFCondition result; + DcmDataset* dataset = NULL; + OFVector datasets; + OFVector::const_iterator it = files.begin(); + while (it != files.end()) { - DCMFG_ERROR("Could not load file " << (*it) << ": " << result.text()); - return result; + result = dcmff.loadFile((*it).c_str()); + if (result.bad()) + { + DCMFG_ERROR("Could not load file " << (*it) << ": " << result.text()); + return result; + } + dataset = dcmff.getDataset(); + datasets.push_back(dataset); + it++; } - dataset = dcmff.getDataset(); - datasets.push_back(dataset); - it++; - } - return addSourceImageItems(datasets, purposeOfReference, resultSourceImageItems, skipErrors); + return addSourceImageItems(datasets, purposeOfReference, resultSourceImageItems, skipErrors); } - OFCondition DerivationImageItem::addSourceImageItems(const OFVector& datasets, const CodeSequenceMacro& purposeOfReference, OFVector& resultSourceImageItems, const OFBool skipErrors) - { - OFCondition result; - OFVector::const_iterator it = datasets.begin(); - while (it != datasets.end()) - { - SourceImageItem* resultItem = NULL; - result = addSourceImageItem((*it), purposeOfReference, resultItem); - if (result.good()) - { - resultSourceImageItems.push_back(resultItem); - } - else if (result.bad() && !skipErrors) - { - DCMFG_ERROR("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); - break; - } - else if (result.bad()) +{ + OFCondition result; + OFVector::const_iterator it = datasets.begin(); + while (it != datasets.end()) { - DCMFG_WARN("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); + SourceImageItem* resultItem = NULL; + result = addSourceImageItem((*it), purposeOfReference, resultItem); + if (result.good()) + { + resultSourceImageItems.push_back(resultItem); + } + else if (result.bad() && !skipErrors) + { + DCMFG_ERROR("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); + break; + } + else if (result.bad()) + { + DCMFG_WARN("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); + } + it++; } - it++; - } - return result; + return result; } - OFVector& DerivationImageItem::getDerivationCodeItems() { - return m_DerivationCodeItems; + return m_DerivationCodeItems; } - -OFCondition DerivationImageItem::getDerivationDescription(OFString& value, - const long signed int pos) const +OFCondition DerivationImageItem::getDerivationDescription(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromElement(m_DerivationDescription, value, pos); + return DcmIODUtil::getStringValueFromElement(m_DerivationDescription, value, pos); } - -OFCondition DerivationImageItem::setDerivationDescription(const OFString& value, - const OFBool checkValue) +OFCondition DerivationImageItem::setDerivationDescription(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_DerivationDescription.putOFStringArray(value); + (void)checkValue; + return m_DerivationDescription.putOFStringArray(value); } - OFVector& DerivationImageItem::getSourceImageItems() { - return m_SourceImageItems; + return m_SourceImageItems; } - -OFCondition DerivationImageItem::read(DcmItem& itemOfDerivationImageSequence, - const OFBool clearOldData) +OFCondition DerivationImageItem::read(DcmItem& itemOfDerivationImageSequence, const OFBool clearOldData) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - /* re-initialize object */ - if (clearOldData) - clearData(); + /* re-initialize object */ + if (clearOldData) + clearData(); - /* Derivation Description */ - DcmIODUtil::getAndCheckElementFromDataset(itemOfDerivationImageSequence, m_DerivationDescription, "1" /* vm */, "3" /* type */, "DerivationImageMacro"); + /* Derivation Description */ + DcmIODUtil::getAndCheckElementFromDataset( + itemOfDerivationImageSequence, m_DerivationDescription, "1" /* vm */, "3" /* type */, "DerivationImageMacro"); - /* Derivation Code Sequence */ - DcmIODUtil::readSubSequence > - ( itemOfDerivationImageSequence, - DCM_DerivationCodeSequence, - m_DerivationCodeItems, - "1" /* vm */, - "3" /* type */, - "DerivationImageMacro" ); + /* Derivation Code Sequence */ + DcmIODUtil::readSubSequence >(itemOfDerivationImageSequence, + DCM_DerivationCodeSequence, + m_DerivationCodeItems, + "1" /* vm */, + "3" /* type */, + "DerivationImageMacro"); - - /* Source Image Sequence */ - DcmIODUtil::readSubSequence > - ( itemOfDerivationImageSequence, - DCM_SourceImageSequence, - m_SourceImageItems, - "0-n" /* vm */, - "2" /* type */, - "DerivationImageMacro" ); + /* Source Image Sequence */ + DcmIODUtil::readSubSequence >(itemOfDerivationImageSequence, + DCM_SourceImageSequence, + m_SourceImageItems, + "0-n" /* vm */, + "2" /* type */, + "DerivationImageMacro"); return result; } - OFCondition DerivationImageItem::write(DcmItem& itemOfDerivationImageSequence) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; + + /* Write Derivation Description */ + DcmIODUtil::copyElementToDataset( + result, itemOfDerivationImageSequence, m_DerivationDescription, "1", "3", "DerivationImageMacro"); + + /* Write Derivation Code Sequence */ + DcmIODUtil::writeSubSequence >(result, + DCM_DerivationCodeSequence, + m_DerivationCodeItems, + itemOfDerivationImageSequence, + "1-n", + "1", + "DerivationImageMacro"); + + /* Write Source Image Sequence */ + DcmIODUtil::writeSubSequence >(result, + DCM_SourceImageSequence, + m_SourceImageItems, + itemOfDerivationImageSequence, + "0-n", + "2", + "DerivationImageMacro"); - /* Write Derivation Description */ - DcmIODUtil::copyElementToDataset(result, itemOfDerivationImageSequence, m_DerivationDescription, "1", "3", "DerivationImageMacro"); - - /* Write Derivation Code Sequence */ - DcmIODUtil::writeSubSequence > - ( result, - DCM_DerivationCodeSequence, - m_DerivationCodeItems, - itemOfDerivationImageSequence, - "1-n", - "1", - "DerivationImageMacro" ); - - /* Write Source Image Sequence */ - DcmIODUtil::writeSubSequence > - ( result, - DCM_SourceImageSequence, - m_SourceImageItems, - itemOfDerivationImageSequence, - "0-n", - "2", - "DerivationImageMacro" ); - - return result; + return result; } - diff --git a/dcmfg/libsrc/fgfact.cc b/dcmfg/libsrc/fgfact.cc index a7146a93..dfc051ea 100644 --- a/dcmfg/libsrc/fgfact.cc +++ b/dcmfg/libsrc/fgfact.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,136 +20,181 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/iodutil.h" -#include "dcmtk/dcmfg/fgfact.h" + +#include "dcmtk/dcmfg/fgctacquisitiondetails.h" +#include "dcmtk/dcmfg/fgctacquisitiontype.h" +#include "dcmtk/dcmfg/fgctadditionalxraysource.h" +#include "dcmtk/dcmfg/fgctexposure.h" +#include "dcmtk/dcmfg/fgctgeometry.h" +#include "dcmtk/dcmfg/fgctimageframetype.h" +#include "dcmtk/dcmfg/fgctposition.h" +#include "dcmtk/dcmfg/fgctreconstruction.h" +#include "dcmtk/dcmfg/fgcttabledynamics.h" +#include "dcmtk/dcmfg/fgctxraydetails.h" #include "dcmtk/dcmfg/fgderimg.h" +#include "dcmtk/dcmfg/fgfact.h" #include "dcmtk/dcmfg/fgfracon.h" #include "dcmtk/dcmfg/fgframeanatomy.h" #include "dcmtk/dcmfg/fgframevoilut.h" -#include "dcmtk/dcmfg/fgpixeltransform.h" #include "dcmtk/dcmfg/fgimagedatatype.h" +#include "dcmtk/dcmfg/fgirradiationeventid.h" #include "dcmtk/dcmfg/fgparametricmapframetype.h" +#include "dcmtk/dcmfg/fgpixeltransform.h" #include "dcmtk/dcmfg/fgpixmsr.h" #include "dcmtk/dcmfg/fgplanor.h" #include "dcmtk/dcmfg/fgplanorvol.h" #include "dcmtk/dcmfg/fgplanpo.h" #include "dcmtk/dcmfg/fgplanposvol.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" #include "dcmtk/dcmfg/fgseg.h" +#include "dcmtk/dcmfg/fgtemporalposition.h" #include "dcmtk/dcmfg/fgusimagedescription.h" -#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" - +#include "dcmtk/dcmiod/iodutil.h" FGFactory* FGFactory::m_Instance = NULL; FGFactory::FGFactory() { - // noting to do (private constructor) + // noting to do (private constructor) } - - FGFactory& FGFactory::instance() { - if (m_Instance == NULL) - { - m_Instance = new FGFactory(); - } - return *m_Instance; + if (m_Instance == NULL) + { + m_Instance = new FGFactory(); + } + return *m_Instance; } - FGBase* FGFactory::create(const DcmFGTypes::E_FGType fgtype) { - switch(fgtype) - { - case DcmFGTypes::EFG_PIXELMEASURES: - return new FGPixelMeasures(); - break; - case DcmFGTypes::EFG_FRAMEANATOMY: - return new FGFrameAnatomy(); - break; - case DcmFGTypes::EFG_FRAMECONTENT: - return new FGFrameContent(); - break; - case DcmFGTypes::EFG_FRAMEVOILUTMETA: // Frame VOI LUT and Frame VOI LUT with LUT - return new FGFrameVOILUT(); - break; - case DcmFGTypes::EFG_PARAMETRICMAPFRAMETYPE: - return new FGParametricMapFrameType; - break; - case DcmFGTypes::EFG_PLANEPOSPATIENT: - return new FGPlanePosPatient(); - break; - case DcmFGTypes::EFG_PLANEPOSITIONVOLUME: - return new FGPlanePositionVolume(); - case DcmFGTypes::EFG_PLANEORIENTPATIENT: - return new FGPlaneOrientationPatient(); - break; - case DcmFGTypes::EFG_PLANEORIENTVOLUME: - return new FGPlaneOrientationVolume(); - case DcmFGTypes::EFG_DERIVATIONIMAGE: - return new FGDerivationImage(); - break; - case DcmFGTypes::EFG_PIXELVALUETRANSMETA: // Pixel Value Transformation Macro or Identity Pixel Value Transformation Macro: - return new FGPixelValueTransformation(); - break; - case DcmFGTypes::EFG_IMAGEDATATYPE: - return new FGImageDataType(); - break; - case DcmFGTypes::EFG_REALWORLDVALUEMAPPING: - return new FGRealWorldValueMapping(); - break; - case DcmFGTypes::EFG_SEGMENTATION: - return new FGSegmentation(); - break; - case DcmFGTypes::EFG_USIMAGEDESCRIPTION: - return new FGUSImageDescription(); - break; - case DcmFGTypes::EFG_CARDIACSYNC: - case DcmFGTypes::EFG_CONTRASTBOLUSUSAGE: - case DcmFGTypes::EFG_PIXELINTENSITYRELLUT: - case DcmFGTypes::EFG_FRAMEPIXELSHIFT: - case DcmFGTypes::EFG_PATIENTORIENTINFRAME: - case DcmFGTypes::EFG_FRAMEDISPLAYSHUTTER: - case DcmFGTypes::EFG_RESPIRATORYSYNC: - case DcmFGTypes::EFG_IRRADIATIONEVENTIDENT: - case DcmFGTypes::EFG_RADIOPHARAMAUSAGE: - case DcmFGTypes::EFG_PATIENTPHYSIOSTATE: - case DcmFGTypes::EFG_TEMPORALPOSITION: - { - DCMFG_DEBUG("Encountered functional group that is not explicitly supported yet:" << DcmFGTypes::FGType2OFString(fgtype)); - return NULL; - break; - } - default: + switch (fgtype) { - DCMFG_DEBUG("Encountered unknown functional group"); - return NULL; - break; + case DcmFGTypes::EFG_PIXELMEASURES: + return new FGPixelMeasures(); + break; + case DcmFGTypes::EFG_FRAMEANATOMY: + return new FGFrameAnatomy(); + break; + case DcmFGTypes::EFG_FRAMECONTENT: + return new FGFrameContent(); + break; + case DcmFGTypes::EFG_CTACQUISITIONDETAILS: + return new FGCTAcquisitionDetails(); + break; + case DcmFGTypes::EFG_CTACQUISITIONTYPE: + return new FGCTAcquisitionType(); + break; + case DcmFGTypes::EFG_CTADDITIONALXRAYSOURCE: + return new FGCTAdditionalXRaySource(); + break; + case DcmFGTypes::EFG_CTEXPOSURE: + return new FGCTExposure(); + break; + case DcmFGTypes::EFG_CTGEOMETRY: + return new FGCTGeometry(); + break; + case DcmFGTypes::EFG_CTIMAGEFRAMETYPE: + return new FGCTImageFrameType(); + break; + case DcmFGTypes::EFG_CTPOSITION: + return new FGCTPosition(); + break; + case DcmFGTypes::EFG_CTRECONSTRUCTION: + return new FGCTReconstruction(); + break; + case DcmFGTypes::EFG_CTTABLEDYNAMICS: + return new FGCTTableDynamics(); + break; + case DcmFGTypes::EFG_CTXRAYDETAILS: + return new FGCTXRayDetails(); + break; + case DcmFGTypes::EFG_IRRADIATIONEVENTIDENT: + return new FGIrradiationEventIdentification(); + break; + case DcmFGTypes::EFG_FRAMEVOILUTMETA: // Frame VOI LUT and Frame VOI LUT with LUT + return new FGFrameVOILUT(); + break; + case DcmFGTypes::EFG_PARAMETRICMAPFRAMETYPE: + return new FGParametricMapFrameType; + break; + case DcmFGTypes::EFG_PLANEPOSPATIENT: + return new FGPlanePosPatient(); + break; + case DcmFGTypes::EFG_PLANEPOSITIONVOLUME: + return new FGPlanePositionVolume(); + break; + case DcmFGTypes::EFG_PLANEORIENTPATIENT: + return new FGPlaneOrientationPatient(); + break; + case DcmFGTypes::EFG_PLANEORIENTVOLUME: + return new FGPlaneOrientationVolume(); + case DcmFGTypes::EFG_DERIVATIONIMAGE: + return new FGDerivationImage(); + break; + case DcmFGTypes::EFG_PIXELVALUETRANSMETA: // Pixel Value Transformation Macro or Identity Pixel Value + // Transformation Macro: + return new FGPixelValueTransformation(); + break; + case DcmFGTypes::EFG_IMAGEDATATYPE: + return new FGImageDataType(); + break; + case DcmFGTypes::EFG_REALWORLDVALUEMAPPING: + return new FGRealWorldValueMapping(); + break; + case DcmFGTypes::EFG_SEGMENTATION: + return new FGSegmentation(); + break; + case DcmFGTypes::EFG_TEMPORALPOSITION: + return new FGTemporalPosition(); + break; + case DcmFGTypes::EFG_USIMAGEDESCRIPTION: + return new FGUSImageDescription(); + break; + case DcmFGTypes::EFG_CARDIACSYNC: + case DcmFGTypes::EFG_CONTRASTBOLUSUSAGE: + case DcmFGTypes::EFG_PIXELINTENSITYRELLUT: + case DcmFGTypes::EFG_FRAMEPIXELSHIFT: + case DcmFGTypes::EFG_PATIENTORIENTINFRAME: + case DcmFGTypes::EFG_FRAMEDISPLAYSHUTTER: + case DcmFGTypes::EFG_RESPIRATORYSYNC: + case DcmFGTypes::EFG_RADIOPHARAMAUSAGE: + case DcmFGTypes::EFG_PATIENTPHYSIOSTATE: + { + DCMFG_DEBUG("Encountered functional group that is not explicitly supported yet:" + << DcmFGTypes::FGType2OFString(fgtype)); + return NULL; + break; + } + default: + { + DCMFG_DEBUG("Encountered unknown functional group"); + return NULL; + break; + } } - } - return NULL; + return NULL; } - FGBase* FGFactory::create(const DcmTagKey& fgSequenceKey) { - if (!DcmIODUtil::isSequenceTag(fgSequenceKey)) - { - DCMFG_ERROR("Cannot create functional group from non-sequence tag"); - return NULL; - } - FGBase* fg = NULL; - DcmFGTypes::E_FGType fgType = DcmFGTypes::tagKey2FGType(fgSequenceKey); - if (fgType != DcmFGTypes::EFG_UNKNOWN) - { - fg = create(fgType); - } - /* if the sequence is know but there is no specific implementation, create generic functional group */ - if (fg == NULL) - { - DCMFG_DEBUG("Encountered unknown functional group, started by tag key: " << fgSequenceKey); - fg = new FGUnknown(fgSequenceKey); - } - return fg; + if (!DcmIODUtil::isSequenceTag(fgSequenceKey)) + { + DCMFG_ERROR("Cannot create functional group from non-sequence tag"); + return NULL; + } + FGBase* fg = NULL; + DcmFGTypes::E_FGType fgType = DcmFGTypes::tagKey2FGType(fgSequenceKey); + if (fgType != DcmFGTypes::EFG_UNKNOWN) + { + fg = create(fgType); + } + /* if the sequence is know but there is no specific implementation, create generic functional group */ + if (fg == NULL) + { + DCMFG_DEBUG("Encountered unknown functional group, started by tag key: " << fgSequenceKey); + fg = new FGUnknown(fgSequenceKey); + } + return fg; } diff --git a/dcmfg/libsrc/fgfracon.cc b/dcmfg/libsrc/fgfracon.cc index e24a4c35..133a7cb2 100644 --- a/dcmfg/libsrc/fgfracon.cc +++ b/dcmfg/libsrc/fgfracon.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,357 +20,321 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/fgfracon.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" // Constructor -FGFrameContent::FGFrameContent() : - FGBase(DcmFGTypes::EFG_FRAMECONTENT), - m_FrameAcquisitonNumber(DCM_FrameAcquisitionNumber), - m_FrameReferenceDateTime(DCM_FrameReferenceDateTime), - m_FrameAcquisitionDateTime(DCM_FrameAcquisitionDateTime), - m_FrameAcquisitionDuration(DCM_FrameAcquisitionDuration), - m_CardiacCyclePosition(DCM_CardiacCyclePosition), - m_RespiratoryCyclePosition(DCM_RespiratoryCyclePosition), - m_DimensionIndexValues(DCM_DimensionIndexValues), - m_TemporalPositionIndex(DCM_TemporalPositionIndex), - m_StackID(DCM_StackID), - m_InStackPositionNumber(DCM_InStackPositionNumber), - m_FrameComments(DCM_FrameComments), - m_FrameLabel(DCM_FrameLabel) +FGFrameContent::FGFrameContent() + : FGBase(DcmFGTypes::EFG_FRAMECONTENT) + , m_FrameAcquisitonNumber(DCM_FrameAcquisitionNumber) + , m_FrameReferenceDateTime(DCM_FrameReferenceDateTime) + , m_FrameAcquisitionDateTime(DCM_FrameAcquisitionDateTime) + , m_FrameAcquisitionDuration(DCM_FrameAcquisitionDuration) + , m_CardiacCyclePosition(DCM_CardiacCyclePosition) + , m_RespiratoryCyclePosition(DCM_RespiratoryCyclePosition) + , m_DimensionIndexValues(DCM_DimensionIndexValues) + , m_TemporalPositionIndex(DCM_TemporalPositionIndex) + , m_StackID(DCM_StackID) + , m_InStackPositionNumber(DCM_InStackPositionNumber) + , m_FrameComments(DCM_FrameComments) + , m_FrameLabel(DCM_FrameLabel) { } - FGFrameContent::~FGFrameContent() { - // nothing to do + // nothing to do } - FGBase* FGFrameContent::clone() const { - FGFrameContent* copy = new FGFrameContent(); - if (copy) - { - copy->m_FrameAcquisitonNumber = this->m_FrameAcquisitonNumber; - copy->m_FrameReferenceDateTime = this->m_FrameReferenceDateTime; - copy->m_FrameAcquisitionDateTime = this->m_FrameAcquisitionDateTime; - copy->m_FrameAcquisitionDuration = this->m_FrameAcquisitionDuration; - copy->m_CardiacCyclePosition = this->m_CardiacCyclePosition; - copy->m_RespiratoryCyclePosition = this->m_RespiratoryCyclePosition; - copy->m_DimensionIndexValues = this->m_DimensionIndexValues; - copy->m_TemporalPositionIndex = this->m_TemporalPositionIndex; - copy->m_StackID = this->m_StackID; - copy->m_InStackPositionNumber = this->m_InStackPositionNumber; - copy->m_FrameComments = this->m_FrameComments; - copy->m_FrameLabel = this->m_FrameLabel; - } - return copy; + FGFrameContent* copy = new FGFrameContent(); + if (copy) + { + copy->m_FrameAcquisitonNumber = this->m_FrameAcquisitonNumber; + copy->m_FrameReferenceDateTime = this->m_FrameReferenceDateTime; + copy->m_FrameAcquisitionDateTime = this->m_FrameAcquisitionDateTime; + copy->m_FrameAcquisitionDuration = this->m_FrameAcquisitionDuration; + copy->m_CardiacCyclePosition = this->m_CardiacCyclePosition; + copy->m_RespiratoryCyclePosition = this->m_RespiratoryCyclePosition; + copy->m_DimensionIndexValues = this->m_DimensionIndexValues; + copy->m_TemporalPositionIndex = this->m_TemporalPositionIndex; + copy->m_StackID = this->m_StackID; + copy->m_InStackPositionNumber = this->m_InStackPositionNumber; + copy->m_FrameComments = this->m_FrameComments; + copy->m_FrameLabel = this->m_FrameLabel; + } + return copy; } - void FGFrameContent::clearData() { - m_FrameAcquisitonNumber.clear(); - m_FrameReferenceDateTime.clear(); - m_FrameAcquisitionDateTime.clear(); - m_FrameAcquisitionDuration.clear(); - m_CardiacCyclePosition.clear(); - m_RespiratoryCyclePosition.clear(); - m_DimensionIndexValues.clear(); - m_TemporalPositionIndex.clear(); - m_StackID.clear(); - m_InStackPositionNumber.clear(); - m_FrameComments.clear(); - m_FrameLabel.clear(); + m_FrameAcquisitonNumber.clear(); + m_FrameReferenceDateTime.clear(); + m_FrameAcquisitionDateTime.clear(); + m_FrameAcquisitionDuration.clear(); + m_CardiacCyclePosition.clear(); + m_RespiratoryCyclePosition.clear(); + m_DimensionIndexValues.clear(); + m_TemporalPositionIndex.clear(); + m_StackID.clear(); + m_InStackPositionNumber.clear(); + m_FrameComments.clear(); + m_FrameLabel.clear(); } - OFCondition FGFrameContent::check() const { - // Maybe add checks later - return EC_Normal; + // Maybe add checks later + return EC_Normal; } - /// Read Frame Content Sequence from given item OFCondition FGFrameContent::read(DcmItem& item) { - clearData(); - - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_FrameContentSequence, 0, seqItem); - if (result.bad()) - return result; + clearData(); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_StackID, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_FrameContentSequence, 0, seqItem); + if (result.bad()) + return result; - return EC_Normal; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_StackID, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); + return EC_Normal; } /// Writes single Frame Content Sequence into given item OFCondition FGFrameContent::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_FrameContentSequence, 0, seqItem); - if (result.bad()) + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_FrameContentSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_StackID, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); return result; - - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_StackID, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); - return result; } - int FGFrameContent::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGFrameContent* myRhs = OFstatic_cast(const FGFrameContent*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_FrameAcquisitonNumber.compare(myRhs->m_FrameAcquisitonNumber); + if (result == 0) + result = m_FrameReferenceDateTime.compare(myRhs->m_FrameReferenceDateTime); + if (result == 0) + result = m_FrameAcquisitionDateTime.compare(myRhs->m_FrameAcquisitionDateTime); + if (result == 0) + result = m_FrameAcquisitionDuration.compare(myRhs->m_FrameAcquisitionDuration); + if (result == 0) + result = m_CardiacCyclePosition.compare(myRhs->m_CardiacCyclePosition); + if (result == 0) + result = m_RespiratoryCyclePosition.compare(myRhs->m_RespiratoryCyclePosition); + if (result == 0) + result = m_DimensionIndexValues.compare(myRhs->m_DimensionIndexValues); + if (result == 0) + result = m_TemporalPositionIndex.compare(myRhs->m_TemporalPositionIndex); + if (result == 0) + result = m_StackID.compare(myRhs->m_StackID); + if (result == 0) + result = m_InStackPositionNumber.compare(myRhs->m_InStackPositionNumber); + if (result == 0) + result = m_FrameComments.compare(myRhs->m_FrameComments); + if (result == 0) + result = m_FrameLabel.compare(myRhs->m_FrameLabel); - const FGFrameContent* myRhs = OFstatic_cast(const FGFrameContent*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_FrameAcquisitonNumber.compare(myRhs->m_FrameAcquisitonNumber); - if (result == 0) - result = m_FrameReferenceDateTime.compare(myRhs->m_FrameReferenceDateTime); - if (result == 0) - result = m_FrameAcquisitionDateTime.compare(myRhs->m_FrameAcquisitionDateTime); - if (result == 0) - result = m_FrameAcquisitionDuration.compare(myRhs->m_FrameAcquisitionDuration); - if (result == 0) - result = m_CardiacCyclePosition.compare(myRhs->m_CardiacCyclePosition); - if (result == 0) - result = m_RespiratoryCyclePosition.compare(myRhs->m_RespiratoryCyclePosition); - if (result == 0) - result = m_DimensionIndexValues.compare(myRhs->m_DimensionIndexValues); - if (result == 0) - result = m_TemporalPositionIndex.compare(myRhs->m_TemporalPositionIndex); - if (result == 0) - result = m_StackID.compare(myRhs->m_StackID); - if (result == 0) - result = m_InStackPositionNumber.compare(myRhs->m_InStackPositionNumber); - if (result == 0) - result = m_FrameComments.compare(myRhs->m_FrameComments); - if (result == 0) - result = m_FrameLabel.compare(myRhs->m_FrameLabel); - - return result; + return result; } - // --- get() functionality --- -OFCondition FGFrameContent::getFrameAcquisitionNumber(Uint16& value, - const signed long pos) +OFCondition FGFrameContent::getFrameAcquisitionNumber(Uint16& value, const unsigned long pos) { - return m_FrameAcquisitonNumber.getUint16(value, pos); + return m_FrameAcquisitonNumber.getUint16(value, pos); } -OFCondition FGFrameContent::getFrameReferenceDateTime(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getFrameReferenceDateTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_FrameReferenceDateTime, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameReferenceDateTime, value, pos); } -OFCondition FGFrameContent::getFrameAcquisitionDateTime(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getFrameAcquisitionDateTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_FrameAcquisitionDateTime, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameAcquisitionDateTime, value, pos); } -OFCondition FGFrameContent::getFrameAcquisitionDuration(Float64& value, - const unsigned long pos) +OFCondition FGFrameContent::getFrameAcquisitionDuration(Float64& value, const unsigned long pos) { - return m_FrameAcquisitionDuration.getFloat64(value, pos); + return m_FrameAcquisitionDuration.getFloat64(value, pos); } -OFCondition FGFrameContent::getCardiacCyclePosition(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getCardiacCyclePosition(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_CardiacCyclePosition, value, pos); + return DcmIODUtil::getStringValueFromElement(m_CardiacCyclePosition, value, pos); } -OFCondition FGFrameContent::getRespiratoryCyclePosition(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getRespiratoryCyclePosition(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_RespiratoryCyclePosition, value, pos); + return DcmIODUtil::getStringValueFromElement(m_RespiratoryCyclePosition, value, pos); } -OFCondition FGFrameContent::getDimensionIndexValues(Uint32& value, - const signed long pos) +OFCondition FGFrameContent::getDimensionIndexValues(Uint32& value, const unsigned long pos) { - return m_DimensionIndexValues.getUint32(value, pos); + return m_DimensionIndexValues.getUint32(value, pos); } -OFCondition FGFrameContent::getTemporalPositionIndex(Uint32& value, - const signed long pos) +OFCondition FGFrameContent::getTemporalPositionIndex(Uint32& value, const unsigned long pos) { - return m_TemporalPositionIndex.getUint32(value, pos); + return m_TemporalPositionIndex.getUint32(value, pos); } -OFCondition FGFrameContent::getStackID(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getStackID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_StackID, value, pos); + return DcmIODUtil::getStringValueFromElement(m_StackID, value, pos); } -OFCondition FGFrameContent::getInStackPositionNumber(Uint32& value, - const long signed int pos) +OFCondition FGFrameContent::getInStackPositionNumber(Uint32& value, const unsigned long pos) { - return m_InStackPositionNumber.getUint32(value, pos); + return m_InStackPositionNumber.getUint32(value, pos); } - -OFCondition FGFrameContent::getFrameComments(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getFrameComments(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_FrameComments, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameComments, value, pos); } -OFCondition FGFrameContent::getFrameLabel(OFString& value, - const signed long pos) +OFCondition FGFrameContent::getFrameLabel(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_FrameLabel, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameLabel, value, pos); } // --- set() functionality --- -OFCondition FGFrameContent::setFrameAcquisitionNumber(const Uint16& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameAcquisitionNumber(const Uint16& value, const OFBool checkValue) { - (void)checkValue; - m_FrameAcquisitonNumber.putUint16(value); - return EC_Normal; + (void)checkValue; + m_FrameAcquisitonNumber.putUint16(value); + return EC_Normal; } -OFCondition FGFrameContent::setFrameReferenceDateTime(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameReferenceDateTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_FrameReferenceDateTime.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameReferenceDateTime.putOFStringArray(value); + return result; } -OFCondition FGFrameContent::setFrameAcquisitionDateTime(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameAcquisitionDateTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_FrameAcquisitionDateTime.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameAcquisitionDateTime.putOFStringArray(value); + return result; } -OFCondition FGFrameContent::setFrameAcquisitionDuration(const Float64& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameAcquisitionDuration(const Float64& value, const OFBool checkValue) { - (void)checkValue; - // basic checking always included - return m_FrameAcquisitionDuration.putFloat64(value); + (void)checkValue; + // basic checking always included + return m_FrameAcquisitionDuration.putFloat64(value); } -OFCondition FGFrameContent::setCardiacCyclePosition(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setCardiacCyclePosition(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_CardiacCyclePosition.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_CardiacCyclePosition.putOFStringArray(value); + return result; } -OFCondition FGFrameContent::setRespiratoryCyclePosition(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setRespiratoryCyclePosition(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_RespiratoryCyclePosition.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_RespiratoryCyclePosition.putOFStringArray(value); + return result; } -OFCondition FGFrameContent::setDimensionIndexValues(const Uint32& value, - const unsigned int dim, - const OFBool checkValue) +OFCondition +FGFrameContent::setDimensionIndexValues(const Uint32& value, const unsigned int dim, const OFBool checkValue) { - // no other meaningful checks possible in this context - (void)checkValue; - if (value == 0) - { - DCMFG_ERROR("Cannot set dimension index value 0, must be >= 1)"); - return EC_InvalidValue; - } - return m_DimensionIndexValues.putUint32(value, dim); + // no other meaningful checks possible in this context + (void)checkValue; + if (value == 0) + { + DCMFG_ERROR("Cannot set dimension index value 0, must be >= 1)"); + return EC_InvalidValue; + } + return m_DimensionIndexValues.putUint32(value, dim); } -OFCondition FGFrameContent::setTemporalPositionIndex(const Uint32& value, - const OFBool checkValue) +OFCondition FGFrameContent::setTemporalPositionIndex(const Uint32& value, const OFBool checkValue) { - // no meaningful check possible in this context - (void)checkValue; - return m_TemporalPositionIndex.putUint32(value); + // no meaningful check possible in this context + (void)checkValue; + return m_TemporalPositionIndex.putUint32(value); } -OFCondition FGFrameContent::setStackID(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setStackID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_StackID.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_StackID.putOFStringArray(value); + return result; } - -OFCondition FGFrameContent::setInStackPositionNumber(const Uint32& value, - const OFBool checkValue) +OFCondition FGFrameContent::setInStackPositionNumber(const Uint32& value, const OFBool checkValue) { - // no meaningful check possible in this context - (void)checkValue; - return m_InStackPositionNumber.putUint32(value); + // no meaningful check possible in this context + (void)checkValue; + return m_InStackPositionNumber.putUint32(value); } - -OFCondition FGFrameContent::setFrameComments(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameComments(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_FrameComments.putOFStringArray(value); + (void)checkValue; + return m_FrameComments.putOFStringArray(value); } - -OFCondition FGFrameContent::setFrameLabel(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameContent::setFrameLabel(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_FrameLabel.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameLabel.putOFStringArray(value); + return result; } - diff --git a/dcmfg/libsrc/fgframeanatomy.cc b/dcmfg/libsrc/fgframeanatomy.cc index 22a9ea41..57e7a40e 100644 --- a/dcmfg/libsrc/fgframeanatomy.cc +++ b/dcmfg/libsrc/fgframeanatomy.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,187 +19,177 @@ * */ - #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgframeanatomy.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgframeanatomy.h" #include "dcmtk/dcmiod/iodutil.h" - FGFrameAnatomy::FGFrameAnatomy() -: FGBase(DcmFGTypes::EFG_FRAMEANATOMY), - m_FrameLaterality(LATERALITY_UNDEFINED), - m_Anatomy("1" /* Use Mandatory version of macro, i.e. make "Anatomic Region Sequence type 1" */) + : FGBase(DcmFGTypes::EFG_FRAMEANATOMY) + , m_FrameLaterality(LATERALITY_UNDEFINED) + , m_Anatomy("1" /* Use Mandatory version of macro, i.e. make "Anatomic Region Sequence type 1" */) { } - FGFrameAnatomy::~FGFrameAnatomy() { - // nothing to do + // nothing to do } - FGBase* FGFrameAnatomy::clone() const { - FGFrameAnatomy* copy = new FGFrameAnatomy(); - if (copy) - { - copy->m_FrameLaterality= this->m_FrameLaterality; - copy->m_Anatomy = this->m_Anatomy; - } - return copy; + FGFrameAnatomy* copy = new FGFrameAnatomy(); + if (copy) + { + copy->m_FrameLaterality = this->m_FrameLaterality; + copy->m_Anatomy = this->m_Anatomy; + } + return copy; } - void FGFrameAnatomy::clearData() { - m_FrameLaterality = LATERALITY_UNDEFINED; - m_Anatomy.clearData(); + m_FrameLaterality = LATERALITY_UNDEFINED; + m_Anatomy.clearData(); } - OFCondition FGFrameAnatomy::check() const { - if (!isLateralityValid(m_FrameLaterality)) - { - DCMFG_ERROR("Frame Laterality invalid"); - return FG_EC_InvalidData; - } - return OFconst_cast(GeneralAnatomyMacro*, &m_Anatomy)->check(); + if (!isLateralityValid(m_FrameLaterality)) + { + DCMFG_ERROR("Frame Laterality invalid"); + return FG_EC_InvalidData; + } + return OFconst_cast(GeneralAnatomyMacro*, &m_Anatomy)->check(); } - int FGFrameAnatomy::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGFrameAnatomy* myRhs = OFstatic_cast(const FGFrameAnatomy*, &rhs); - if (!myRhs) - return -1; + const FGFrameAnatomy* myRhs = OFstatic_cast(const FGFrameAnatomy*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - if (m_FrameLaterality != myRhs->m_FrameLaterality) - return 1; + // Compare all elements + if (m_FrameLaterality != myRhs->m_FrameLaterality) + return 1; - return m_Anatomy.compare(myRhs->m_Anatomy); + return m_Anatomy.compare(myRhs->m_Anatomy); } - /// Read from Frame Content Sequence OFCondition FGFrameAnatomy::read(DcmItem& item) { - clearData(); + clearData(); - OFCondition result; - DcmItem* seqItem = NULL; - result = getItemFromFGSequence(item, DCM_FrameAnatomySequence, 0, seqItem); - if (result.bad()) - return result; + OFCondition result; + DcmItem* seqItem = NULL; + result = getItemFromFGSequence(item, DCM_FrameAnatomySequence, 0, seqItem); + if (result.bad()) + return result; - DcmCodeString elem(DCM_FrameLaterality); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, elem, "1", "1", "FrameAnatomyMacro"); - OFString val; - elem.getOFStringArray(val); - m_FrameLaterality = str2Laterality(val); + DcmCodeString elem(DCM_FrameLaterality); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, elem, "1", "1", "FrameAnatomyMacro"); + OFString val; + elem.getOFStringArray(val); + m_FrameLaterality = str2Laterality(val); - m_Anatomy.read(*seqItem); + m_Anatomy.read(*seqItem); - return EC_Normal; + return EC_Normal; } - OFCondition FGFrameAnatomy::write(DcmItem& item) { - OFCondition result = check(); - if (result.good()) - { - DcmItem* seqItem = NULL; - result = createNewFGSequence(item, DCM_FrameAnatomySequence, 0, seqItem); + OFCondition result = check(); if (result.good()) { - OFString lat = laterality2Str(m_FrameLaterality); - result = seqItem->putAndInsertOFStringArray(DCM_FrameLaterality, lat); - if (result.good()) - { - result = m_Anatomy.write(*seqItem); - } + DcmItem* seqItem = NULL; + result = createNewFGSequence(item, DCM_FrameAnatomySequence, 0, seqItem); + if (result.good()) + { + OFString lat = laterality2Str(m_FrameLaterality); + result = seqItem->putAndInsertOFStringArray(DCM_FrameLaterality, lat); + if (result.good()) + { + result = m_Anatomy.write(*seqItem); + } + } } - } - return result; + return result; } - OFCondition FGFrameAnatomy::getLaterality(FGFrameAnatomy::LATERALITY& value) { - value = m_FrameLaterality; - return EC_Normal; + value = m_FrameLaterality; + return EC_Normal; } - GeneralAnatomyMacro& FGFrameAnatomy::getAnatomy() { - return m_Anatomy; + return m_Anatomy; } - OFCondition FGFrameAnatomy::setLaterality(const FGFrameAnatomy::LATERALITY& value) { - if (isLateralityValid(value)) - { - m_FrameLaterality = value; - return EC_Normal; - } - else - { - return FG_EC_InvalidData; - } + if (isLateralityValid(value)) + { + m_FrameLaterality = value; + return EC_Normal; + } + else + { + return FG_EC_InvalidData; + } } - OFString FGFrameAnatomy::laterality2Str(const FGFrameAnatomy::LATERALITY lat) { - switch(lat) - { - case LATERALITY_INVALID: return "Invalid"; - case LATERALITY_L: return "L"; - case LATERALITY_R: return "R"; - case LATERALITY_BOTH: return "B"; - case LATERALITY_UNDEFINED: return "Undefined"; - case LATERALITY_UNPAIRED: return "U"; - default: return "Invalid"; - } + switch (lat) + { + case LATERALITY_INVALID: + return "Invalid"; + case LATERALITY_L: + return "L"; + case LATERALITY_R: + return "R"; + case LATERALITY_BOTH: + return "B"; + case LATERALITY_UNDEFINED: + return "Undefined"; + case LATERALITY_UNPAIRED: + return "U"; + default: + return "Invalid"; + } } - FGFrameAnatomy::LATERALITY FGFrameAnatomy::str2Laterality(const OFString& lat) { - if (lat == "L") - return LATERALITY_L; - if (lat == "R") - return LATERALITY_R; - if (lat == "U") - return LATERALITY_UNPAIRED; - if (lat == "B") - return LATERALITY_BOTH; - - if (lat.empty()) - return LATERALITY_UNDEFINED; - - return LATERALITY_INVALID; - + if (lat == "L") + return LATERALITY_L; + if (lat == "R") + return LATERALITY_R; + if (lat == "U") + return LATERALITY_UNPAIRED; + if (lat == "B") + return LATERALITY_BOTH; + + if (lat.empty()) + return LATERALITY_UNDEFINED; + + return LATERALITY_INVALID; } - OFBool FGFrameAnatomy::isLateralityValid(const FGFrameAnatomy::LATERALITY lat) { - if ( (lat == LATERALITY_L) || (lat == LATERALITY_R) || (lat == LATERALITY_BOTH) || - (lat == LATERALITY_UNPAIRED) ) - return OFTrue; - else - return OFFalse; + if ((lat == LATERALITY_L) || (lat == LATERALITY_R) || (lat == LATERALITY_BOTH) || (lat == LATERALITY_UNPAIRED)) + return OFTrue; + else + return OFFalse; } - diff --git a/dcmfg/libsrc/fgframevoilut.cc b/dcmfg/libsrc/fgframevoilut.cc index 9a85ba54..214fe9cc 100644 --- a/dcmfg/libsrc/fgframevoilut.cc +++ b/dcmfg/libsrc/fgframevoilut.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,206 +20,191 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/fgframevoilut.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_Brain = "BRAIN"; +const OFString FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_SoftTissue = "SOFT_TISSUE"; +const OFString FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_Lung = "LUNG"; +const OFString FGFrameVOILUT::DT_CT_WindowCenterWidthExplanation_Bone = "BONE"; // Constructor -FGFrameVOILUT::FGFrameVOILUT() : - FGBase(DcmFGTypes::EFG_FRAMEVOILUTMETA), - m_WindowCenter(DCM_WindowCenter), - m_WindowWidth(DCM_WindowWidth), - m_WindowCenterWindowWidthExplanation(DCM_WindowCenterWidthExplanation), - m_VOILUTFunction(DCM_VOILUTFunction) +FGFrameVOILUT::FGFrameVOILUT() + : FGBase(DcmFGTypes::EFG_FRAMEVOILUTMETA) + , m_WindowCenter(DCM_WindowCenter) + , m_WindowWidth(DCM_WindowWidth) + , m_WindowCenterWindowWidthExplanation(DCM_WindowCenterWidthExplanation) + , m_VOILUTFunction(DCM_VOILUTFunction) { } - FGFrameVOILUT::~FGFrameVOILUT() { - // nothing to do + // nothing to do } - FGBase* FGFrameVOILUT::clone() const { - FGFrameVOILUT* copy = new FGFrameVOILUT(); - if (copy) - { - copy->m_WindowCenter = this->m_WindowCenter; - copy->m_WindowWidth= this->m_WindowWidth; - copy->m_WindowCenterWindowWidthExplanation = this->m_WindowCenterWindowWidthExplanation; - copy->m_VOILUTFunction= this->m_VOILUTFunction; - } - return copy; + FGFrameVOILUT* copy = new FGFrameVOILUT(); + if (copy) + { + copy->m_WindowCenter = this->m_WindowCenter; + copy->m_WindowWidth = this->m_WindowWidth; + copy->m_WindowCenterWindowWidthExplanation = this->m_WindowCenterWindowWidthExplanation; + copy->m_VOILUTFunction = this->m_VOILUTFunction; + } + return copy; } - void FGFrameVOILUT::clearData() { - m_WindowCenter.clear(); - m_WindowWidth.clear(); - m_WindowCenterWindowWidthExplanation.clear(); - m_VOILUTFunction.clear(); + m_WindowCenter.clear(); + m_WindowWidth.clear(); + m_WindowCenterWindowWidthExplanation.clear(); + m_VOILUTFunction.clear(); } - OFCondition FGFrameVOILUT::check() const { - // For now attribute-based checks in read() and write() are sufficient - return EC_Normal; + // For now attribute-based checks in read() and write() are sufficient + return EC_Normal; } - // --- get() functionality --- - -OFCondition FGFrameVOILUT::getWindowCenter(Float64& value, - const unsigned long pos) +OFCondition FGFrameVOILUT::getWindowCenter(Float64& value, const unsigned long pos) { - return m_WindowCenter.getFloat64(value, pos); + return m_WindowCenter.getFloat64(value, pos); } - -OFCondition FGFrameVOILUT::getWindowWidth(Float64& value, - const unsigned long pos) +OFCondition FGFrameVOILUT::getWindowWidth(Float64& value, const unsigned long pos) { - return m_WindowWidth.getFloat64(value, pos); + return m_WindowWidth.getFloat64(value, pos); } - -OFCondition FGFrameVOILUT::getWindowCenterAndWindowWidthExplanation(OFString& value, - const unsigned long pos) +OFCondition FGFrameVOILUT::getWindowCenterAndWindowWidthExplanation(OFString& value, const unsigned long pos) { - return m_WindowCenterWindowWidthExplanation.getOFString(value, pos); + return m_WindowCenterWindowWidthExplanation.getOFString(value, pos); } - -OFCondition FGFrameVOILUT::getCenterWidthExplanation(Float64& windowCenter, - Float64& windowWidth, - OFString& explanation) +OFCondition FGFrameVOILUT::getCenterWidthExplanation(Float64& windowCenter, Float64& windowWidth, OFString& explanation) { - OFCondition result = m_WindowCenter.getFloat64(windowCenter); - if (result.good()) result = m_WindowWidth.getFloat64(windowWidth); - if (result.good()) result = m_WindowCenterWindowWidthExplanation.getOFString(explanation, 0); - return result; + OFCondition result = m_WindowCenter.getFloat64(windowCenter); + if (result.good()) + result = m_WindowWidth.getFloat64(windowWidth); + if (result.good()) + result = m_WindowCenterWindowWidthExplanation.getOFString(explanation, 0); + return result; } - -OFCondition FGFrameVOILUT::getVOILUTFunction(OFString& value, - const unsigned long pos) +OFCondition FGFrameVOILUT::getVOILUTFunction(OFString& value, const unsigned long pos) { - return m_VOILUTFunction.getOFString(value, pos); + return m_VOILUTFunction.getOFString(value, pos); } - // --- set() functionality --- - -OFCondition FGFrameVOILUT::setWindowCenter(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameVOILUT::setWindowCenter(const OFString& value, const OFBool checkValue) { - // no checks at the moment - (void)checkValue; - return m_WindowCenter.putOFStringArray(value); + // no checks at the moment + (void)checkValue; + return m_WindowCenter.putOFStringArray(value); } -OFCondition FGFrameVOILUT::setWindowWidth(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameVOILUT::setWindowWidth(const OFString& value, const OFBool checkValue) { - // no checks at the moment - (void)checkValue; - return m_WindowWidth.putOFStringArray(value); + // no checks at the moment + (void)checkValue; + return m_WindowWidth.putOFStringArray(value); } - OFCondition FGFrameVOILUT::setCenterWidthExplanation(const Float64& windowCenter, const Float64& windowWidth, const OFString& explanation, const OFBool checkValue) { - OFCondition result = m_WindowCenter.putFloat64(windowCenter); - if (result.good()) result = m_WindowWidth.putFloat64(windowWidth); - if (result.good() && !explanation.empty()) - { - if (checkValue) - { - result = (checkValue) ? DcmLongString::checkStringValue(explanation, "1") : EC_Normal; - } + OFCondition result = m_WindowCenter.putFloat64(windowCenter); if (result.good()) + result = m_WindowWidth.putFloat64(windowWidth); + if (result.good() && !explanation.empty()) { - result = m_WindowCenterWindowWidthExplanation.putString(explanation.c_str()); + if (checkValue) + { + result = (checkValue) ? DcmLongString::checkStringValue(explanation, "1") : EC_Normal; + } + if (result.good()) + { + result = m_WindowCenterWindowWidthExplanation.putString(explanation.c_str()); + } } - } - return result; + return result; } - -OFCondition FGFrameVOILUT::setVOILUTFunction(const OFString& value, - const OFBool checkValue) +OFCondition FGFrameVOILUT::setVOILUTFunction(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_VOILUTFunction.putString(value.c_str()); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VOILUTFunction.putString(value.c_str()); + return result; } - /// Read Frame Content Sequence from given item OFCondition FGFrameVOILUT::read(DcmItem& item) { - clearData(); - - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); - if (result.bad()) - return result; + clearData(); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); + if (result.bad()) + return result; - return EC_Normal; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); + return EC_Normal; } /// Writes single Frame Content Sequence into given item OFCondition FGFrameVOILUT::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); - if (result.bad()) + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); return result; - - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); - return result; } - int FGFrameVOILUT::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGFrameVOILUT* myRhs = OFstatic_cast(const FGFrameVOILUT*, &rhs); - if (!myRhs) - return -1; + const FGFrameVOILUT* myRhs = OFstatic_cast(const FGFrameVOILUT*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - result = m_WindowCenter.compare(myRhs->m_WindowCenter); - if (result == 0) - result = m_WindowWidth.compare(myRhs->m_WindowWidth); - if (result == 0) - result = m_WindowCenterWindowWidthExplanation.compare(myRhs->m_WindowCenterWindowWidthExplanation); - if (result == 0) - result = m_VOILUTFunction.compare(myRhs->m_VOILUTFunction); + // Compare all elements + result = m_WindowCenter.compare(myRhs->m_WindowCenter); + if (result == 0) + result = m_WindowWidth.compare(myRhs->m_WindowWidth); + if (result == 0) + result = m_WindowCenterWindowWidthExplanation.compare(myRhs->m_WindowCenterWindowWidthExplanation); + if (result == 0) + result = m_VOILUTFunction.compare(myRhs->m_VOILUTFunction); - return result; + return result; } diff --git a/dcmfg/libsrc/fgimagedatatype.cc b/dcmfg/libsrc/fgimagedatatype.cc index 782ee443..a3b81db2b 100644 --- a/dcmfg/libsrc/fgimagedatatype.cc +++ b/dcmfg/libsrc/fgimagedatatype.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,250 +20,233 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/fgimagedatatype.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" // Constructor -FGImageDataType::FGImageDataType() : - FGBase(DcmFGTypes::EFG_IMAGEDATATYPE), - m_DataType(DCM_DataType), - m_AliasedDataType(DCM_AliasedDataType), - m_ZeroVelocityPixelValueUS(DCM_ZeroVelocityPixelValue), - m_ZeroVelocityPixelValueSS(DCM_ZeroVelocityPixelValue) +FGImageDataType::FGImageDataType() + : FGBase(DcmFGTypes::EFG_IMAGEDATATYPE) + , m_DataType(DCM_DataType) + , m_AliasedDataType(DCM_AliasedDataType) + , m_ZeroVelocityPixelValueUS(DCM_ZeroVelocityPixelValue) + , m_ZeroVelocityPixelValueSS(DCM_ZeroVelocityPixelValue) { } - FGImageDataType::~FGImageDataType() { - // nothing to do + // nothing to do } - FGBase* FGImageDataType::clone() const { - FGImageDataType* copy = new FGImageDataType(); - if (copy) - { - copy->m_DataType = this->m_DataType; - copy->m_AliasedDataType= this->m_AliasedDataType; - if (! OFconst_cast(DcmSignedShort*, &this->m_ZeroVelocityPixelValueSS)->isEmpty()) - { - copy->m_ZeroVelocityPixelValueSS = this->m_ZeroVelocityPixelValueSS; - } - else if (! OFconst_cast(DcmUnsignedShort*, &this->m_ZeroVelocityPixelValueUS)->isEmpty()) + FGImageDataType* copy = new FGImageDataType(); + if (copy) { - copy->m_ZeroVelocityPixelValueUS = this->m_ZeroVelocityPixelValueUS; + copy->m_DataType = this->m_DataType; + copy->m_AliasedDataType = this->m_AliasedDataType; + if (!OFconst_cast(DcmSignedShort*, &this->m_ZeroVelocityPixelValueSS)->isEmpty()) + { + copy->m_ZeroVelocityPixelValueSS = this->m_ZeroVelocityPixelValueSS; + } + else if (!OFconst_cast(DcmUnsignedShort*, &this->m_ZeroVelocityPixelValueUS)->isEmpty()) + { + copy->m_ZeroVelocityPixelValueUS = this->m_ZeroVelocityPixelValueUS; + } + // both emtpy? nothing to do then } - // both emtpy? nothing to do then - } - return copy; + return copy; } - void FGImageDataType::clearData() { - m_DataType.clear(); - m_AliasedDataType.clear(); - m_ZeroVelocityPixelValueSS.clear(); - m_ZeroVelocityPixelValueUS.clear(); + m_DataType.clear(); + m_AliasedDataType.clear(); + m_ZeroVelocityPixelValueSS.clear(); + m_ZeroVelocityPixelValueUS.clear(); } - OFCondition FGImageDataType::check() const { - // For now, checks in read() and write() are sufficient - return EC_Normal; + // For now, checks in read() and write() are sufficient + return EC_Normal; } - // --- get() functionality --- -OFCondition FGImageDataType::getDataType(OFString& value, - const long signed int pos) +OFCondition FGImageDataType::getDataType(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_DataType, value, pos); + return DcmIODUtil::getStringValueFromElement(m_DataType, value, pos); } - OFCondition FGImageDataType::getAliasedDataType(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_AliasedDataType, value, pos); + return DcmIODUtil::getStringValueFromElement(m_AliasedDataType, value, pos); } - -OFCondition FGImageDataType::getZeroVelocityPixelValue(Sint32& value, - const long signed int pos) +OFCondition FGImageDataType::getZeroVelocityPixelValue(Sint32& value, const unsigned long pos) { - OFCondition result; - if (!m_ZeroVelocityPixelValueSS.isEmpty()) - { - Sint16 val = 0; - if ( (result = m_ZeroVelocityPixelValueSS.getSint16(val, pos)).good()) + OFCondition result; + if (!m_ZeroVelocityPixelValueSS.isEmpty()) { - value = val; + Sint16 val = 0; + if ((result = m_ZeroVelocityPixelValueSS.getSint16(val, pos)).good()) + { + value = val; + } } - } - else if (!m_ZeroVelocityPixelValueUS.isEmpty()) - { - Uint16 val = 0; - if ( (result = m_ZeroVelocityPixelValueUS.getUint16(val, pos)).good()) + else if (!m_ZeroVelocityPixelValueUS.isEmpty()) { - value = val; + Uint16 val = 0; + if ((result = m_ZeroVelocityPixelValueUS.getUint16(val, pos)).good()) + { + value = val; + } } - } - else - return EC_TagNotFound; + else + return EC_TagNotFound; - return EC_Normal; + return EC_Normal; } - // --- set() functionality --- - -OFCondition FGImageDataType::setDataType(const OFString& value, - const OFBool checkValue) +OFCondition FGImageDataType::setDataType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_DataType.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_DataType.putOFStringArray(value); + return result; } - -OFCondition FGImageDataType::setAliasedDataType(const OFString& value, - const OFBool checkValue) +OFCondition FGImageDataType::setAliasedDataType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_AliasedDataType.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AliasedDataType.putOFStringArray(value); + return result; } - OFCondition FGImageDataType::setZeroVelocityPixelValueSS(const Sint16 value) { - return m_ZeroVelocityPixelValueSS.putSint16(value); + return m_ZeroVelocityPixelValueSS.putSint16(value); } - OFCondition FGImageDataType::setZeroVelocityPixelValueUS(const Uint16 value) { - return m_ZeroVelocityPixelValueUS.putUint16(value); + return m_ZeroVelocityPixelValueUS.putUint16(value); } - // Read Frame Content Sequence from given item OFCondition FGImageDataType::read(DcmItem& item) { - clearData(); - - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); - if (result.bad()) - return result; - - DcmElement* elem = NULL; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); - // We do not know the VR of Zero Velocity Pixel Value (US or SS), so we cannot - // use the regular getAndCheckElementFromDataset() method that implicitly gets - // this information via the provided element. Instead, get element first and - // and then check it in an extra step, afterwards access value depending on - // the element's VR. - seqItem->findAndGetElement(DCM_ZeroVelocityPixelValue, elem); - DcmIODUtil::checkElementValue(elem, DCM_ZeroVelocityPixelValue, "1", "1C", EC_Normal, "ImageDataTypeMacro"); - if (elem) - { - if (elem->getVR() == EVR_SS) - { - m_ZeroVelocityPixelValueSS.copyFrom(*elem); - } - else if (elem->getVR() == EVR_US) - { - m_ZeroVelocityPixelValueUS.copyFrom(*elem); - } - else + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmElement* elem = NULL; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); + // We do not know the VR of Zero Velocity Pixel Value (US or SS), so we cannot + // use the regular getAndCheckElementFromDataset() method that implicitly gets + // this information via the provided element. Instead, get element first and + // and then check it in an extra step, afterwards access value depending on + // the element's VR. + seqItem->findAndGetElement(DCM_ZeroVelocityPixelValue, elem); + DcmIODUtil::checkElementValue(elem, DCM_ZeroVelocityPixelValue, "1", "1C", EC_Normal, "ImageDataTypeMacro"); + if (elem) { - Uint16 pixrep = 0; - if (item.findAndGetUint16(DCM_PixelRepresentation, pixrep).good()) - { - if (pixrep == 0) + if (elem->getVR() == EVR_SS) + { + m_ZeroVelocityPixelValueSS.copyFrom(*elem); + } + else if (elem->getVR() == EVR_US) { - m_ZeroVelocityPixelValueUS.putUint16(pixrep, 0); + m_ZeroVelocityPixelValueUS.copyFrom(*elem); } else { - m_ZeroVelocityPixelValueSS.putSint16(pixrep, 1); + Uint16 pixrep = 0; + if (item.findAndGetUint16(DCM_PixelRepresentation, pixrep).good()) + { + if (pixrep == 0) + { + m_ZeroVelocityPixelValueUS.putUint16(0, 0); + } + else + { + m_ZeroVelocityPixelValueSS.putSint16(1, 1); + } + } + else + { + DCMFG_ERROR("Cannot read Zero Velocity Pixel Value"); + } } - } - else - { - DCMFG_ERROR("Cannot read Zero Velocity Pixel Value"); - } } - } - return EC_Normal; + return EC_Normal; } - // Writes single Frame Content Sequence into given item OFCondition FGImageDataType::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); - if (result.bad()) - return result; - - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); - if (!m_ZeroVelocityPixelValueSS.isEmpty()) - { - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueSS, "1", "1C", "ImageDataTypeMacro"); - } else if (!m_ZeroVelocityPixelValueUS.isEmpty()) - { - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueUS, "1", "1C", "ImageDataTypeMacro"); - } - // Zero Velocity Pixel Value is required in case Data Type is TISSUE_VELOCITY, - // FLOW_VELOCITY or DIRECTION_POWER. - else - { - OFString val; - m_DataType.getOFStringArray(val); - if ( (val == "TISSUE_VELOCITY") || (val == "FLOW_VELOCITY") || (val == "DIRECTION_POWER") ) + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); + if (!m_ZeroVelocityPixelValueSS.isEmpty()) { - DCMFG_ERROR("Missing value for Zero Velocity Pixel Value (required if Data Type has" << - "the value TISSUE_VELOCITY, FLOW_VELOCITY or DIRECTION_POWER"); - return FG_EC_InvalidData; + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueSS, "1", "1C", "ImageDataTypeMacro"); + } + else if (!m_ZeroVelocityPixelValueUS.isEmpty()) + { + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueUS, "1", "1C", "ImageDataTypeMacro"); + } + // Zero Velocity Pixel Value is required in case Data Type is TISSUE_VELOCITY, + // FLOW_VELOCITY or DIRECTION_POWER. + else + { + OFString val; + m_DataType.getOFStringArray(val); + if ((val == "TISSUE_VELOCITY") || (val == "FLOW_VELOCITY") || (val == "DIRECTION_POWER")) + { + DCMFG_ERROR("Missing value for Zero Velocity Pixel Value (required if Data Type has" + << "the value TISSUE_VELOCITY, FLOW_VELOCITY or DIRECTION_POWER"); + return FG_EC_InvalidData; + } } - } - return result; + return result; } - int FGImageDataType::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGImageDataType* myRhs = OFstatic_cast(const FGImageDataType*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_DataType.compare(myRhs->m_DataType); + if (result == 0) + result = m_AliasedDataType.compare(myRhs->m_AliasedDataType); + if (result == 0) + result = m_ZeroVelocityPixelValueSS.compare(myRhs->m_ZeroVelocityPixelValueSS); + if (result == 0) + result = m_ZeroVelocityPixelValueUS.compare(myRhs->m_ZeroVelocityPixelValueUS); - const FGImageDataType* myRhs = OFstatic_cast(const FGImageDataType*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_DataType.compare(myRhs->m_DataType); - if (result == 0) - result = m_AliasedDataType.compare(myRhs->m_AliasedDataType); - if (result == 0) - result = m_ZeroVelocityPixelValueSS.compare(myRhs->m_ZeroVelocityPixelValueSS); - if (result == 0) - result = m_ZeroVelocityPixelValueUS.compare(myRhs->m_ZeroVelocityPixelValueUS); - - return result; + return result; } diff --git a/dcmfg/libsrc/fginterface.cc b/dcmfg/libsrc/fginterface.cc index 03b17c78..81ce51a7 100644 --- a/dcmfg/libsrc/fginterface.cc +++ b/dcmfg/libsrc/fginterface.cc @@ -20,699 +20,671 @@ */ #include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmfg/fg.h" +#include "dcmtk/dcmfg/fgfact.h" // for creating new functional groups +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/dcmiod/iodutil.h" // for static helpers #include "dcmtk/ofstd/ofmap.h" #include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/dcmiod/iodutil.h" // for static helpers -#include "dcmtk/dcmfg/fginterface.h" -#include "dcmtk/dcmfg/fg.h" -#include "dcmtk/dcmfg/fgfact.h" // for creating new functional groups - -FGInterface::FGInterface() : -m_shared(), -m_perFrame(), -m_checkOnWrite(OFTrue) +FGInterface::FGInterface() + : m_shared() + , m_perFrame() + , m_checkOnWrite(OFTrue) { } - FGInterface::~FGInterface() { - clear(); + clear(); } - void FGInterface::clear() { - // Clear per frame functional groups - while (m_perFrame.size() > 0) - { - OFMap::iterator it = m_perFrame.begin(); - FunctionalGroups* fg = (*it).second; - m_perFrame.erase(it); - delete fg; - } + // Clear per frame functional groups + while (m_perFrame.size() > 0) + { + OFMap::iterator it = m_perFrame.begin(); + FunctionalGroups* fg = (*it).second; + m_perFrame.erase(it); + delete fg; + } - // Clear shared functional groups - m_shared.clear(); + // Clear shared functional groups + m_shared.clear(); } - size_t FGInterface::getNumberOfFrames() { - return m_perFrame.size(); + return m_perFrame.size(); } - OFCondition FGInterface::addShared(const FGBase& group) { - DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); - if ( sharedType == DcmFGTypes::EFGS_ONLYPERFRAME ) - { - DCMFG_ERROR("Cannot add group as shared, per DICOM, group type " << DcmFGTypes::FGType2OFString(group.getType()) << " is always per-frame"); - return FG_EC_CouldNotAddFG; - } - - // Delete all per frame groups of this type - for (size_t count = 0; count < m_perFrame.size(); count++) - { - deletePerFrame(OFstatic_cast(Uint32, count), group.getType()); - } - - // Create copy for insertion - FGBase* copy = group.clone(); - if (!copy) - { - return EC_MemoryExhausted; - } - - // Insert shared one, replace old one if existing - OFCondition result = insertShared(copy, OFTrue /* replace */); - if (result.bad()) - { - DCMFG_ERROR("Could not add shared group of type: " << DcmFGTypes::FGType2OFString(group.getType())); - delete copy; - } - - return result; -} - - -OFCondition FGInterface::addPerFrame(const Uint32 frameNo, - const FGBase& group) -{ - OFCondition result = EC_Normal; - DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); - if ( sharedType == DcmFGTypes::EFGS_ONLYSHARED) - { - DCMFG_ERROR("Cannot add group as per-frame, group type " << DcmFGTypes::FGType2OFString(group.getType()) << " is always shared"); - return FG_EC_CouldNotAddFG; - } - - // Check whether there is already a shared group of this type. - // If the content is equal to the given group, we re-use the shared one - FGBase* shared = getShared(group.getType()); - // If there is a shared group - if ( shared ) - { - // If shared has identical values as given group, nothing has to be done. - // Else if shared group with such type exists, but content differs, - // we must the make the existing shared FG "per-frame", i.e. distribute - // it to all frames, and add the given group for the given frame. - if ( (*shared).compare(group) != 0 ) - { - // We need to unshare this group, i.e. distribute it to frames - DCMFG_DEBUG("Converting shared group of type " << DcmFGTypes::FGType2OFString(group.getType()) << " to per-frame, triggered by deviating per-frame insertion"); - result = convertSharedToPerFrame(group.getType()); + DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); + if (sharedType == DcmFGTypes::EFGS_ONLYPERFRAME) + { + DCMFG_ERROR("Cannot add group as shared, per DICOM, group type " << DcmFGTypes::FGType2OFString(group.getType()) + << " is always per-frame"); + return FG_EC_CouldNotAddFG; } - else + + // Delete all per frame groups of this type + for (size_t count = 0; count < m_perFrame.size(); count++) { - DCMFG_DEBUG("Re-using shared group instead of adding per-frame for frame " << frameNo << ", type " << DcmFGTypes::FGType2OFString(group.getType())); - return EC_Normal; + deletePerFrame(OFstatic_cast(Uint32, count), group.getType()); } - } - if (result.good()) - { + // Create copy for insertion FGBase* copy = group.clone(); if (!copy) { - return EC_MemoryExhausted; + return EC_MemoryExhausted; } - result = insertPerFrame(frameNo, copy); + + // Insert shared one, replace old one if existing + OFCondition result = insertShared(copy, OFTrue /* replace */); if (result.bad()) - delete copy; - } + { + DCMFG_ERROR("Could not add shared group of type: " << DcmFGTypes::FGType2OFString(group.getType())); + delete copy; + } - return result; + return result; } +OFCondition FGInterface::addPerFrame(const Uint32 frameNo, const FGBase& group) +{ + OFCondition result = EC_Normal; + DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); + if (sharedType == DcmFGTypes::EFGS_ONLYSHARED) + { + DCMFG_ERROR("Cannot add group as per-frame, group type " << DcmFGTypes::FGType2OFString(group.getType()) + << " is always shared"); + return FG_EC_CouldNotAddFG; + } + + // Check whether there is already a shared group of this type. + // If the content is equal to the given group, we re-use the shared one + FGBase* shared = getShared(group.getType()); + // If there is a shared group + if (shared) + { + // If shared has identical values as given group, nothing has to be done. + // Else if shared group with such type exists, but content differs, + // we must the make the existing shared FG "per-frame", i.e. distribute + // it to all frames, and add the given group for the given frame. + if ((*shared).compare(group) != 0) + { + // We need to unshare this group, i.e. distribute it to frames + DCMFG_DEBUG("Converting shared group of type " << DcmFGTypes::FGType2OFString( + group.getType()) << " to per-frame, triggered by deviating per-frame insertion"); + result = convertSharedToPerFrame(group.getType()); + } + else + { + DCMFG_DEBUG("Re-using shared group instead of adding per-frame for frame " + << frameNo << ", type " << DcmFGTypes::FGType2OFString(group.getType())); + return EC_Normal; + } + } + + if (result.good()) + { + FGBase* copy = group.clone(); + if (!copy) + { + return EC_MemoryExhausted; + } + result = insertPerFrame(frameNo, copy); + if (result.bad()) + delete copy; + } + + return result; +} // Get specific functional group for a frame, // no matter whether it is stored per frame or shared -FGBase* FGInterface::get(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType) +FGBase* FGInterface::get(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType) { - OFBool helpShared; // throw-away variable - return get(frameNo, fgType, helpShared); + OFBool helpShared; // throw-away variable + return get(frameNo, fgType, helpShared); } - const FunctionalGroups* FGInterface::getPerFrame(const Uint32 frameNo) const { - if (frameNo > m_perFrame.size()) - { - return NULL; - } - else - { - return (*(m_perFrame.find(frameNo))).second; - } + if (frameNo > m_perFrame.size()) + { + return NULL; + } + else + { + return (*(m_perFrame.find(frameNo))).second; + } } - const FunctionalGroups* FGInterface::getShared() const { - return &m_shared; + return &m_shared; } - // Read enhanced multi-frame information from DICOM item, usually DcmDataset OFCondition FGInterface::read(DcmItem& dataset) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - // clear any old values - clear(); + // clear any old values + clear(); - /* read shared functional groups */ - if (result.good()) - { - result = readSharedFG(dataset); - } - - /* read per frame functional groups */ - if (result.good()) - { - result = readPerFrameFG(dataset); - } + /* read shared functional groups */ + if (result.good()) + { + result = readSharedFG(dataset); + } - return result; + /* read per frame functional groups */ + if (result.good()) + { + result = readPerFrameFG(dataset); + } + return result; } - OFCondition FGInterface::readSharedFG(DcmItem& dataset) { - /* read shared functional groups */ - DcmSequenceOfItems *shared = NULL; - OFCondition result = dataset.findAndGetSequence(DCM_SharedFunctionalGroupsSequence, shared); - if (result.bad()) - { - DCMFG_ERROR("Could not find Shared Functional Group Sequence"); - return FG_EC_NoSharedFG; - } - - if (shared->card() > 1) - { - DCMFG_WARN("More than one item in Shared Functional Group Sequence, only considering the first one"); - } - else if (shared->card() == 0) - { - DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one expected"); - return FG_EC_NoSharedFG; - } - - // get the only item of shared functional group sequence - DcmItem* sharedFGs = shared->getItem(0); - // read all functional groups from shared fg sequence item - result = readSingleFG(*sharedFGs, m_shared); - - return result; -} - - + /* read shared functional groups */ + DcmSequenceOfItems* shared = NULL; + OFCondition result = dataset.findAndGetSequence(DCM_SharedFunctionalGroupsSequence, shared); + if (result.bad()) + { + DCMFG_ERROR("Could not find Shared Functional Group Sequence"); + return FG_EC_NoSharedFG; + } -OFCondition FGInterface::readPerFrameFG(DcmItem& dataset) -{ - /* read per-frame functional groups */ - DcmSequenceOfItems *perFrame = NULL; - OFCondition result = dataset.findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame); - if (result.bad()) - { - DCMFG_ERROR("Could not find Per-Frame Functional Group Sequence"); - return FG_EC_NoPerFrameFG; - } - - /* 1-n items required */ - size_t numFrames = perFrame->card(); - if (numFrames == 0) - { - DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one or more expected"); - return FG_EC_NoPerFrameFG; - } - - /* Read functional groups for each item (one per frame) */ - DcmItem *oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(NULL)); - Uint32 count = 0; - while (oneFrameItem != NULL) - { - OFunique_ptr perFrameGroups(new FunctionalGroups()); - if (!oneFrameItem) - { - DCMFG_ERROR("Could not get functional group item for frame #" << count << " (internal error)"); - } - else if (!perFrameGroups.get()) - { - DCMFG_ERROR("Could not create functional groups for frame #" << count << ": Memory exhausted?"); + if (shared->card() > 1) + { + DCMFG_WARN("More than one item in Shared Functional Group Sequence, only considering the first one"); } - else + else if (shared->card() == 0) { - result = readSingleFG(*oneFrameItem, *perFrameGroups); - if (result.good()) - { - if ( !m_perFrame.insert( OFMake_pair(count, perFrameGroups.release()) ).second ) - { - DCMFG_ERROR("Could not store functional groups for frame #" << count << " (internal error)"); - } - } - else - { - DCMFG_ERROR("Could not read functional groups for frame #" << count << ": " << result.text()); - } - } - oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(oneFrameItem)); - count++; - } - return EC_Normal; // for now we always return EC_Normal... -} + DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one expected"); + return FG_EC_NoSharedFG; + } + // get the only item of shared functional group sequence + DcmItem* sharedFGs = shared->getItem(0); + // read all functional groups from shared fg sequence item + result = readSingleFG(*sharedFGs, m_shared); + return result; +} -OFCondition FGInterface::readSingleFG(DcmItem& fgItem, - FunctionalGroups& groups) +OFCondition FGInterface::readPerFrameFG(DcmItem& dataset) { - OFCondition result; - size_t card = fgItem.card(); - OFString fgname; - for (size_t count = 0; count < card; count++) - { - DcmElement *elem = fgItem.getElement(OFstatic_cast(unsigned long, count)); - // TODO: non-sequence elements are not explicitly forbidden here(?), we could store them and re-store them later - if (elem->getVR() != EVR_SQ) + /* read per-frame functional groups */ + DcmSequenceOfItems* perFrame = NULL; + OFCondition result = dataset.findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame); + if (result.bad()) { - DCMFG_WARN("Found non-sequence element in functional group sequence item (ignored): " << elem->getTag()); + DCMFG_ERROR("Could not find Per-Frame Functional Group Sequence"); + return FG_EC_NoPerFrameFG; } - else + + /* 1-n items required */ + size_t numFrames = perFrame->card(); + if (numFrames == 0) { - FGBase *fg = FGFactory::instance().create(elem->getTag()); - if (fg != NULL) - { - OFStringStream stream; - stream << DcmFGTypes::tagKey2FGString(elem->getTag()) << " " << elem->getTag(); - OFSTRINGSTREAM_GETSTR(stream,tmpstr) - fgname = tmpstr; - OFSTRINGSTREAM_FREESTR(tmpstr) - result = fg->read(fgItem); - if (result.bad()) + DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one or more expected"); + return FG_EC_NoPerFrameFG; + } + + /* Read functional groups for each item (one per frame) */ + DcmItem* oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(NULL)); + Uint32 count = 0; + while (oneFrameItem != NULL) + { + OFunique_ptr perFrameGroups(new FunctionalGroups()); + if (!oneFrameItem) { - DCMFG_WARN("Cannot read functional group: " << fgname << " (ignored)"); + DCMFG_ERROR("Could not get functional group item for frame #" << count << " (internal error)"); } - // we also accept groups while reading which could instantiated but not could not be read - result = groups.insert(fg, OFTrue); - if (result.good()) + else if (!perFrameGroups.get()) { - DCMFG_DEBUG("Inserted functional group: " << fgname ); + DCMFG_ERROR("Could not create functional groups for frame #" << count << ": Memory exhausted?"); } else { - DCMFG_ERROR("Could not insert functional group: " << fgname << " (internal error)"); - delete fg; + result = readSingleFG(*oneFrameItem, *perFrameGroups); + if (result.good()) + { + if (!m_perFrame.insert(OFMake_pair(count, perFrameGroups.release())).second) + { + DCMFG_ERROR("Could not store functional groups for frame #" << count << " (internal error)"); + } + } + else + { + DCMFG_ERROR("Could not read functional groups for frame #" << count << ": " << result.text()); + } } - } - else - { - DCMFG_WARN("Cannot understand functional group for sequence tag: " << elem->getTag()); - } - } - } - return EC_Normal; // for now we always return EC_Normal... + oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(oneFrameItem)); + count++; + } + return EC_Normal; // for now we always return EC_Normal... } +OFCondition FGInterface::readSingleFG(DcmItem& fgItem, FunctionalGroups& groups) +{ + OFCondition result; + size_t card = fgItem.card(); + OFString fgname; + for (size_t count = 0; count < card; count++) + { + DcmElement* elem = fgItem.getElement(OFstatic_cast(unsigned long, count)); + // TODO: non-sequence elements are not explicitly forbidden here(?), we could store them and re-store them later + if (elem->getVR() != EVR_SQ) + { + DCMFG_WARN("Found non-sequence element in functional group sequence item (ignored): " << elem->getTag()); + } + else + { + FGBase* fg = FGFactory::instance().create(elem->getTag()); + if (fg != NULL) + { + OFStringStream stream; + stream << DcmFGTypes::tagKey2FGString(elem->getTag()) << " " << elem->getTag(); + OFSTRINGSTREAM_GETSTR(stream, tmpstr) + fgname = tmpstr; + OFSTRINGSTREAM_FREESTR(tmpstr) + result = fg->read(fgItem); + if (result.bad()) + { + DCMFG_WARN("Cannot read functional group: " << fgname << " (ignored)"); + } + // we also accept groups while reading which could instantiated but not could not be read + result = groups.insert(fg, OFTrue); + if (result.good()) + { + DCMFG_DEBUG("Inserted functional group: " << fgname); + } + else + { + DCMFG_ERROR("Could not insert functional group: " << fgname << " (internal error)"); + delete fg; + } + } + else + { + DCMFG_WARN("Cannot understand functional group for sequence tag: " << elem->getTag()); + } + } + } + return EC_Normal; // for now we always return EC_Normal... +} // Write enhanced multi-frame information to DICOM item, usually DcmDataset OFCondition FGInterface::write(DcmItem& dataset) { - //Check data integrity of functional group macros */ - if (m_checkOnWrite) - { - if ( !check() ) - return FG_EC_CouldNotWriteFG; - } + // Check data integrity of functional group macros */ + if (m_checkOnWrite) + { + if (!check()) + return FG_EC_CouldNotWriteFG; + } - // Write shared functional Groups - OFCondition result = writeSharedFG(dataset); + // Write shared functional Groups + OFCondition result = writeSharedFG(dataset); - // Write per frame functional groups - if ( result.good() ) result = writePerFrameFG(dataset); + // Write per frame functional groups + if (result.good()) + result = writePerFrameFG(dataset); - return result; + return result; } - FGBase* FGInterface::getShared(const DcmFGTypes::E_FGType fgType) { - return m_shared.find(fgType); + return m_shared.find(fgType); } - -OFCondition FGInterface::insertShared(FGBase* group, - const OFBool replaceExisting) +OFCondition FGInterface::insertShared(FGBase* group, const OFBool replaceExisting) { - return m_shared.insert(group, replaceExisting); + return m_shared.insert(group, replaceExisting); } - -FGBase* FGInterface::getPerFrame(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType) +FGBase* FGInterface::getPerFrame(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType) { - FGBase* group = NULL; - OFMap::iterator it = m_perFrame.find(frameNo); - if ( it != m_perFrame.end() ) - { - FunctionalGroups* perFrameGroups = (*it).second; - group = perFrameGroups->find(fgType); - } - - return group; -} + FGBase* group = NULL; + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + { + FunctionalGroups* perFrameGroups = (*it).second; + group = perFrameGroups->find(fgType); + } + return group; +} OFBool FGInterface::deleteShared(const DcmFGTypes::E_FGType fgType) { - FGBase* group = m_shared.find(fgType); - if (group) - { - delete m_shared.remove(fgType); - return OFTrue; - } - return OFFalse; + FGBase* group = m_shared.find(fgType); + if (group) + { + delete m_shared.remove(fgType); + return OFTrue; + } + return OFFalse; } - - -OFBool FGInterface::deletePerFrame(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType) +OFBool FGInterface::deletePerFrame(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType) { - OFMap::iterator it = m_perFrame.find(frameNo); - if (it != m_perFrame.end()) - { - if ( (*it).second ) - { - FGBase *remove = (*it).second->remove(fgType); - if (remove) - { - DCMFG_DEBUG("Deleting FG for frame " << frameNo << ", type: " << DcmFGTypes::FGType2OFString(fgType)); - delete remove; - remove = NULL; - return OFTrue; - } + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + { + if ((*it).second) + { + FGBase* remove = (*it).second->remove(fgType); + if (remove) + { + DCMFG_DEBUG("Deleting FG for frame " << frameNo << ", type: " << DcmFGTypes::FGType2OFString(fgType)); + delete remove; + remove = NULL; + return OFTrue; + } + } } - } - return OFFalse; + return OFFalse; } - size_t FGInterface::deletePerFrame(const DcmFGTypes::E_FGType fgType) { - size_t numDeleted = 0; - const size_t numFrames = m_perFrame.size(); - for (size_t frameNo = 0; frameNo < numFrames; frameNo++) - { - if (deletePerFrame(OFstatic_cast(Uint32, frameNo), fgType)) + size_t numDeleted = 0; + const size_t numFrames = m_perFrame.size(); + for (size_t frameNo = 0; frameNo < numFrames; frameNo++) { - numDeleted++; + if (deletePerFrame(OFstatic_cast(Uint32, frameNo), fgType)) + { + numDeleted++; + } } - } - return numDeleted; + return numDeleted; } - size_t FGInterface::deleteFrame(const Uint32 frameNo) { - OFMap::iterator it = m_perFrame.find(frameNo); - if (it != m_perFrame.end()) - { - if ( (*it).second ) - { - FunctionalGroups::iterator fg = (*it).second->begin(); - while (fg != (*it).second->end()) - { - delete (*fg).second; - fg++; - } - } - m_perFrame.erase(it); - } - return OFFalse; + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + { + if ((*it).second) + { + FunctionalGroups::iterator fg = (*it).second->begin(); + while (fg != (*it).second->end()) + { + delete (*fg).second; + fg++; + } + } + m_perFrame.erase(it); + } + return OFFalse; } - void FGInterface::setCheckOnWrite(const OFBool doCheck) { - m_checkOnWrite = doCheck; + m_checkOnWrite = doCheck; } - OFBool FGInterface::getCheckOnWrite() { - return m_checkOnWrite; + return m_checkOnWrite; } - FunctionalGroups* FGInterface::getOrCreatePerFrameGroups(const Uint32 frameNo) { - OFMap::iterator it = m_perFrame.find(frameNo); - if (it != m_perFrame.end()) - return (*it).second; - - FunctionalGroups *fg = new FunctionalGroups(); - if (fg != NULL) - { - if ( !(m_perFrame.insert(OFMake_pair(frameNo, fg))).second ) - { - DCMFG_ERROR("Could not insert Per-frame Functional Groups for frame " << frameNo << ": " << "Internal error"); - delete fg; - fg = NULL; - } - } - else - { - DCMFG_ERROR("Could not create Per-frame Functional Groups for frame " << frameNo << ": " << "Memory exhausted"); - } - - return fg; -} + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + return (*it).second; + FunctionalGroups* fg = new FunctionalGroups(); + if (fg != NULL) + { + if (!(m_perFrame.insert(OFMake_pair(frameNo, fg))).second) + { + DCMFG_ERROR("Could not insert Per-frame Functional Groups for frame " << frameNo << ": " + << "Internal error"); + delete fg; + fg = NULL; + } + } + else + { + DCMFG_ERROR("Could not create Per-frame Functional Groups for frame " << frameNo << ": " + << "Memory exhausted"); + } + + return fg; +} OFCondition FGInterface::writePerFrameFG(DcmItem& dataset) { - DCMFG_DEBUG("Writing per-frame functional groups"); - OFCondition result = dataset.insertEmptyElement(DCM_PerFrameFunctionalGroupsSequence, OFTrue); // start with empty sequence - if (result.bad()) - { - DCMFG_ERROR("Could not create Per-frame Functional Groups Sequence"); - return result; - } - - /* Iterate over frames */ - OFMap::iterator it = m_perFrame.begin(); - size_t numFrames = m_perFrame.size(); - for ( size_t count = 0; (count < numFrames) && result.good(); count++) - { - DcmItem* perFrameItem = NULL; - result = dataset.findOrCreateSequenceItem(DCM_PerFrameFunctionalGroupsSequence, perFrameItem, OFstatic_cast(long, count)); - if (result.good()) + DCMFG_DEBUG("Writing per-frame functional groups"); + OFCondition result + = dataset.insertEmptyElement(DCM_PerFrameFunctionalGroupsSequence, OFTrue); // start with empty sequence + if (result.bad()) { - /* Iterate over groups for each frame */ - FunctionalGroups::iterator groupIt = (*it).second->begin(); - while ( result.good() && (groupIt != (*it).second->end()) ) - { - DCMFG_DEBUG("Writing per-frame group: " << DcmFGTypes::FGType2OFString((*groupIt).second->getType()) << " for frame #" << count); - result = (*groupIt).second->write(*perFrameItem); - groupIt++; - } + DCMFG_ERROR("Could not create Per-frame Functional Groups Sequence"); + return result; } - else + + /* Iterate over frames */ + OFMap::iterator it = m_perFrame.begin(); + size_t numFrames = m_perFrame.size(); + for (size_t count = 0; (count < numFrames) && result.good(); count++) { - DCMFG_ERROR("Cannot create item in Per-frame Functional Groups Sequence"); + DcmItem* perFrameItem = NULL; + result = dataset.findOrCreateSequenceItem( + DCM_PerFrameFunctionalGroupsSequence, perFrameItem, OFstatic_cast(long, count)); + if (result.good()) + { + /* Iterate over groups for each frame */ + FunctionalGroups::iterator groupIt = (*it).second->begin(); + while (result.good() && (groupIt != (*it).second->end())) + { + DCMFG_DEBUG("Writing per-frame group: " << DcmFGTypes::FGType2OFString((*groupIt).second->getType()) + << " for frame #" << count); + result = (*groupIt).second->write(*perFrameItem); + groupIt++; + } + } + else + { + DCMFG_ERROR("Cannot create item in Per-frame Functional Groups Sequence"); + } + it++; } - it++; - } - return result; + return result; } - OFCondition FGInterface::writeSharedFG(DcmItem& dataset) { - DCMFG_DEBUG("Writing shared functional groups"); - OFCondition result = dataset.insertEmptyElement(DCM_SharedFunctionalGroupsSequence, OFTrue); // start with empty sequence - DcmItem *sharedFGItem = NULL; - if (result.good()) - { - result = dataset.findOrCreateSequenceItem(DCM_SharedFunctionalGroupsSequence, sharedFGItem, 0); - } - if (result.bad()) - { - DCMFG_ERROR("Could not create Shared Functional Groups Sequence with single item"); + DCMFG_DEBUG("Writing shared functional groups"); + OFCondition result + = dataset.insertEmptyElement(DCM_SharedFunctionalGroupsSequence, OFTrue); // start with empty sequence + DcmItem* sharedFGItem = NULL; + if (result.good()) + { + result = dataset.findOrCreateSequenceItem(DCM_SharedFunctionalGroupsSequence, sharedFGItem, 0); + } + if (result.bad()) + { + DCMFG_ERROR("Could not create Shared Functional Groups Sequence with single item"); + return result; + } + + FunctionalGroups::iterator it = m_shared.begin(); + FunctionalGroups::iterator end = m_shared.end(); + while ((it != end) && result.good()) + { + DCMFG_DEBUG("Writing shared group: " << DcmFGTypes::FGType2OFString((*it).second->getType())); + result = (*it).second->write(*sharedFGItem); + it++; + } return result; - } - - FunctionalGroups::iterator it = m_shared.begin(); - FunctionalGroups::iterator end = m_shared.end(); - while ( (it != end) && result.good() ) - { - DCMFG_DEBUG("Writing shared group: " << DcmFGTypes::FGType2OFString((*it).second->getType())); - result = (*it).second->write(*sharedFGItem); - it++; - } - return result; } - -OFCondition FGInterface::insertPerFrame(const Uint32 frameNo, - FGBase* group, - const OFBool replaceExisting) +OFCondition FGInterface::insertPerFrame(const Uint32 frameNo, FGBase* group, const OFBool replaceExisting) { - if (group == NULL) - return EC_IllegalParameter; + if (group == NULL) + return EC_IllegalParameter; - OFCondition result = EC_Normal; - FGBase* existing = getPerFrame(frameNo, group->getType()); - if (existing) - { - if (replaceExisting) + OFCondition result = EC_Normal; + FGBase* existing = getPerFrame(frameNo, group->getType()); + if (existing) { - DCMFG_DEBUG("Replacing per-frame FG for frame: " << frameNo << ", type: " << DcmFGTypes::FGType2OFString(group->getType())); - deletePerFrame(frameNo, group->getType()); + if (replaceExisting) + { + DCMFG_DEBUG("Replacing per-frame FG for frame: " << frameNo << ", type: " + << DcmFGTypes::FGType2OFString(group->getType())); + deletePerFrame(frameNo, group->getType()); + } + else + { + result = FG_EC_DoubledFG; + } } - else + + // Insert per-frame functional group + if (result.good()) { - result = FG_EC_DoubledFG; + FunctionalGroups* perFrameGroups = getOrCreatePerFrameGroups(frameNo); + if (perFrameGroups != NULL) + { + result = perFrameGroups->insert(group, replaceExisting); + } + else + { + result = FG_EC_CouldNotInsertFG; + } } - } + return result; +} - // Insert per-frame functional group - if (result.good()) - { - FunctionalGroups* perFrameGroups = getOrCreatePerFrameGroups(frameNo); - if (perFrameGroups != NULL) +OFCondition FGInterface::convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType) +{ + FGBase* shared = m_shared.remove(fgType); + if (!shared) { - result = perFrameGroups->insert(group, replaceExisting); + return FG_EC_NoSuchGroup; } - else + + OFCondition result; + size_t numFrames = m_perFrame.size(); + // Walk over all existing frames and copy "old" shared group to them + size_t count = 0; + for (count = 0; result.good() && (count < numFrames); count++) { - result = FG_EC_CouldNotInsertFG; + FGBase* clone = shared->clone(); + if (!clone) + { + result = EC_MemoryExhausted; + } + else + { + result = insertPerFrame(OFstatic_cast(Uint32, count), clone, OFTrue /* replace existing */); + if (result.bad()) + { + delete clone; + } + } } - } - return result; + return result; } - -OFCondition FGInterface::convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType) +FGBase* FGInterface::get(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType, OFBool& isPerFrame) { - FGBase* shared = m_shared.remove(fgType); - if (!shared) - { - return FG_EC_NoSuchGroup; - } - - OFCondition result; - size_t numFrames = m_perFrame.size(); - // Walk over all existing frames and copy "old" shared group to them - size_t count = 0; - for (count = 0; result.good() && (count < numFrames); count++) - { - FGBase* clone = shared->clone(); - if (!clone) - { - result = EC_MemoryExhausted; + FGBase* group = m_shared.find(fgType); + if (!group) + { + group = getPerFrame(frameNo, fgType); + isPerFrame = OFTrue; } else { - result = insertPerFrame(OFstatic_cast(Uint32, count), clone, OFTrue /* replace existing */); - if (result.bad()) - { - delete clone; - } + isPerFrame = OFFalse; } - } - return result ; -} - -FGBase* FGInterface::get(const Uint32 frameNo, - const DcmFGTypes::E_FGType fgType, - OFBool& isPerFrame) -{ - FGBase *group = m_shared.find(fgType); - if ( !group ) - { - group = getPerFrame(frameNo, fgType); - isPerFrame = OFTrue; - } - else - { - isPerFrame = OFFalse; - } - - return group; + return group; } - OFBool FGInterface::check() { - size_t numFrames = m_perFrame.size(); - DCMFG_DEBUG("Checking functional group structure for " << numFrames << " frames"); - size_t numErrors = 0; - for (size_t frameCount = 0; frameCount < numFrames; frameCount++) - { - DCMFG_TRACE("Checking frame " << frameCount << "..."); - // Every frame requires the FrameContent functional group, check "en passant" - OFBool foundFrameContent = OFFalse; - OFMap::iterator frameFG = m_perFrame.begin(); - OFMap::iterator end = m_perFrame.end(); - while (frameFG != end) - { - FunctionalGroups::iterator group = (*frameFG).second->begin(); - FunctionalGroups::iterator groupEnd = (*frameFG).second->end(); - while (group != groupEnd) - { - // Check that per-frame group is not a shared group at the same time - DcmFGTypes::E_FGType groupType = group->second->getType(); - if ( (groupType != DcmFGTypes::EFG_UNDEFINED) && - (groupType != DcmFGTypes::EFG_UNKNOWN) ) + size_t numFrames = m_perFrame.size(); + DCMFG_DEBUG("Checking functional group structure for " << numFrames << " frames"); + size_t numErrors = 0; + for (size_t frameCount = 0; frameCount < numFrames; frameCount++) + { + DCMFG_TRACE("Checking frame " << frameCount << "..."); + // Every frame requires the FrameContent functional group, check "en passant" + OFBool foundFrameContent = OFFalse; + OFMap::iterator frameFG = m_perFrame.begin(); + OFMap::iterator end = m_perFrame.end(); + while (frameFG != end) { - if (m_shared.find(groupType) != NULL) - { - DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) << " is shared AND per-frame for frame " << frameCount); - numErrors++; - } - if (groupType == DcmFGTypes::EFG_FRAMECONTENT) - foundFrameContent = OFTrue; + FunctionalGroups::iterator group = (*frameFG).second->begin(); + FunctionalGroups::iterator groupEnd = (*frameFG).second->end(); + while (group != groupEnd) + { + // Check that per-frame group is not a shared group at the same time + DcmFGTypes::E_FGType groupType = group->second->getType(); + if ((groupType != DcmFGTypes::EFG_UNDEFINED) && (groupType != DcmFGTypes::EFG_UNKNOWN)) + { + if (m_shared.find(groupType) != NULL) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) + << " is shared AND per-frame for frame " << frameCount); + numErrors++; + } + if (groupType == DcmFGTypes::EFG_FRAMECONTENT) + foundFrameContent = OFTrue; + } + // Check if "per-frame" is allowed for this group; + if (group->second->getSharedType() == DcmFGTypes::EFGS_ONLYSHARED) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) + << " can never be per-frame, but found for frame " + << frameCount); + numErrors++; + } + group++; + } + frameFG++; } - // Check if "per-frame" is allowed for this group; - if (group->second->getSharedType() == DcmFGTypes::EFGS_ONLYSHARED) + if (!foundFrameContent) { - DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) << " can never be per-frame, but found for frame " << frameCount); - numErrors++; + DCMFG_ERROR("Frame Content Functional group missing for frame #" << frameCount); + numErrors++; } - group++; - } - frameFG++; } - if (!foundFrameContent) - { - DCMFG_ERROR("Frame Content Functional group missing for frame #" << frameCount); - numErrors++; - } - } - // Check whether shared groups contain FGs that are only permitted per-frame - FunctionalGroups::iterator it = m_shared.begin(); - FunctionalGroups::iterator end = m_shared.end(); - while (it != end) - { - if ( (*it).second->getSharedType() == DcmFGTypes::EFGS_ONLYPERFRAME ) + // Check whether shared groups contain FGs that are only permitted per-frame + FunctionalGroups::iterator it = m_shared.begin(); + FunctionalGroups::iterator end = m_shared.end(); + while (it != end) { - DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString((*it).second->getType()) << " used as shared functional group but must be per-frame"); - numErrors++; + if ((*it).second->getSharedType() == DcmFGTypes::EFGS_ONLYPERFRAME) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString((*it).second->getType()) + << " used as shared functional group but must be per-frame"); + numErrors++; + } + it++; } - it++; - } - if (numErrors > 0) - return OFFalse; + if (numErrors > 0) + return OFFalse; - return OFTrue; + return OFTrue; } diff --git a/dcmfg/libsrc/fgirradiationeventid.cc b/dcmfg/libsrc/fgirradiationeventid.cc new file mode 100644 index 00000000..5490e1a7 --- /dev/null +++ b/dcmfg/libsrc/fgirradiationeventid.cc @@ -0,0 +1,122 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Irradiation Event Identification Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgirradiationeventid.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" + +// Constructor +FGIrradiationEventIdentification::FGIrradiationEventIdentification() + : FGBase(DcmFGTypes::EFG_IRRADIATIONEVENTIDENT) + , m_IrraditionEventUID(DCM_IrradiationEventUID) +{ +} + +FGIrradiationEventIdentification::~FGIrradiationEventIdentification() +{ + // nothing to do +} + +FGBase* FGIrradiationEventIdentification::clone() const +{ + FGIrradiationEventIdentification* copy = new FGIrradiationEventIdentification(); + if (copy) + { + copy->m_IrraditionEventUID = this->m_IrraditionEventUID; + } + return copy; +} + +void FGIrradiationEventIdentification::clearData() +{ + m_IrraditionEventUID.clear(); +} + +OFCondition FGIrradiationEventIdentification::check() const +{ + // Maybe add checks later + return EC_Normal; +} + +// Read Irradiation Event Identification Sequence from given item +OFCondition FGIrradiationEventIdentification::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_IrradiationEventIdentificationSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_IrraditionEventUID, "1", "", "IrradiationEventIdentificationMacro"); + + return EC_Normal; +} + +// Writes single Irradiation Event Identification Sequence into given item +OFCondition FGIrradiationEventIdentification::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_IrradiationEventIdentificationSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write Irradiation Event Identification Sequence attributes --- + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_IrraditionEventUID, "1", "1", "IrradiationEventIdentificationMacro"); + return result; +} + +int FGIrradiationEventIdentification::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGIrradiationEventIdentification* myRhs = OFstatic_cast(const FGIrradiationEventIdentification*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_IrraditionEventUID.compare(myRhs->m_IrraditionEventUID); + return result; +} + +// --- get() functionality --- + +OFCondition FGIrradiationEventIdentification::getIrradiationEventUID(OFString& value, const long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_IrraditionEventUID, value, pos); +} + +// --- set() functionality --- + +OFCondition FGIrradiationEventIdentification::setIrradiationEventUID(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_IrraditionEventUID.putOFStringArray(value); + return result; +} diff --git a/dcmfg/libsrc/fgparametricmapframetype.cc b/dcmfg/libsrc/fgparametricmapframetype.cc index d3956057..66591790 100644 --- a/dcmfg/libsrc/fgparametricmapframetype.cc +++ b/dcmfg/libsrc/fgparametricmapframetype.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,128 +20,120 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/fgparametricmapframetype.h" +#include "dcmtk/dcmiod/iodutil.h" FGParametricMapFrameType::FGParametricMapFrameType() -: FGBase(DcmFGTypes::EFG_PARAMETRICMAPFRAMETYPE) -, m_FrameType(DCM_FrameType) + : FGBase(DcmFGTypes::EFG_PARAMETRICMAPFRAMETYPE) + , m_FrameType(DCM_FrameType) { - } FGParametricMapFrameType::~FGParametricMapFrameType() { - } void FGParametricMapFrameType::clearData() { - m_FrameType.clear(); + m_FrameType.clear(); } FGBase* FGParametricMapFrameType::clone() const { - if(FGParametricMapFrameType* copy = new FGParametricMapFrameType) - { - copy->m_FrameType = m_FrameType; - return copy; - } - return OFnullptr; + if (FGParametricMapFrameType* copy = new FGParametricMapFrameType) + { + copy->m_FrameType = m_FrameType; + return copy; + } + return OFnullptr; } OFCondition FGParametricMapFrameType::read(DcmItem& item) { - clearData(); + clearData(); - DcmItem* seqItem; - OFCondition result; + DcmItem* seqItem; + OFCondition result; - seqItem = OFnullptr; - result = getItemFromFGSequence(item, DCM_ParametricMapFrameTypeSequence, 0, seqItem); - if(result.bad()) - return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "Parametric Map Frame Type"); + seqItem = OFnullptr; + result = getItemFromFGSequence(item, DCM_ParametricMapFrameTypeSequence, 0, seqItem); + if (result.bad()) + return result; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "Parametric Map Frame Type"); - return EC_Normal; + return EC_Normal; } - OFCondition FGParametricMapFrameType::write(DcmItem& item) { - OFCondition result = check(); - if (result.good()) - { - DcmItem* seqItem; - seqItem = OFnullptr; - result = createNewFGSequence(item, DCM_ParametricMapFrameTypeSequence, 0, seqItem); - if(result.good()) + OFCondition result = check(); + if (result.good()) { - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "Parametric Map Frame Type"); + DcmItem* seqItem; + seqItem = OFnullptr; + result = createNewFGSequence(item, DCM_ParametricMapFrameTypeSequence, 0, seqItem); + if (result.good()) + { + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "Parametric Map Frame Type"); + } } - } - return result; + return result; } - int FGParametricMapFrameType::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if(result == 0) - { - const FGParametricMapFrameType* myRhs = OFstatic_cast(const FGParametricMapFrameType*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_FrameType.compare(myRhs->m_FrameType); - } - - return result; -} + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGParametricMapFrameType* myRhs = OFstatic_cast(const FGParametricMapFrameType*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_FrameType.compare(myRhs->m_FrameType); + } + return result; +} OFCondition FGParametricMapFrameType::check() const { - DcmCodeString myFrameType = m_FrameType; - OFCondition result = myFrameType.checkValue("4"); - if (result.good()) - { - OFString val; - myFrameType.getOFString(val, 0); - if (val == "DERIVED") + DcmCodeString myFrameType = m_FrameType; + OFCondition result = myFrameType.checkValue("4"); + if (result.good()) { - val.clear(); - myFrameType.getOFString(val, 1); - if (val == "PRIMARY") - { - val.clear(); - myFrameType.getOFString(val, 1); - return EC_Normal; - } - else - DCMFG_ERROR("Frame Type' 2nd value must be \"PRIMARY\" but is \"" << val << "\""); + OFString val; + myFrameType.getOFString(val, 0); + if (val == "DERIVED") + { + val.clear(); + myFrameType.getOFString(val, 1); + if (val == "PRIMARY") + { + val.clear(); + myFrameType.getOFString(val, 1); + return EC_Normal; + } + else + DCMFG_ERROR("Frame Type' 2nd value must be \"PRIMARY\" but is \"" << val << "\""); + } + else + DCMFG_ERROR("Frame Type 1st value must be \"DERIVED\" but is \"" << val << "\""); } - else - DCMFG_ERROR("Frame Type 1st value must be \"DERIVED\" but is \"" << val << "\""); - } - return FG_EC_InvalidData; + return FG_EC_InvalidData; } - -OFCondition FGParametricMapFrameType::getFrameType(OFString &value, - const signed long pos) const +OFCondition FGParametricMapFrameType::getFrameType(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); } - -OFCondition FGParametricMapFrameType::setFrameType(const OFString &value, - const OFBool checkValue) +OFCondition FGParametricMapFrameType::setFrameType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "4") : EC_Normal; - if (result.good()) - result = m_FrameType.putString(value.c_str()); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "4") : EC_Normal; + if (result.good()) + result = m_FrameType.putString(value.c_str()); + return result; } diff --git a/dcmfg/libsrc/fgpixeltransform.cc b/dcmfg/libsrc/fgpixeltransform.cc index de4b7225..b4b81d2c 100644 --- a/dcmfg/libsrc/fgpixeltransform.cc +++ b/dcmfg/libsrc/fgpixeltransform.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,220 +20,283 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmfg/fgpixeltransform.h" +#include "dcmtk/dcmiod/iodutil.h" FGPixelValueTransformation::FGPixelValueTransformation() -: FGBase(DcmFGTypes::EFG_UNDEFINED) -, m_RescaleIntercept(DCM_RescaleIntercept) -, m_RescaleSlope(DCM_RescaleSlope) -, m_RescaleType(DCM_RescaleType) -, m_UseAsIdentityPixelValueTransformationFG(OFFalse) + : FGBase(DcmFGTypes::EFG_PIXELVALUETRANSMETA) + , m_RescaleIntercept(DCM_RescaleIntercept) + , m_RescaleSlope(DCM_RescaleSlope) + , m_RescaleType(DCM_RescaleType) + , m_fgSubType(E_PixelValTrans_Normal) { - m_RescaleIntercept.putOFStringArray("0"); - m_RescaleSlope.putOFStringArray("1"); - m_RescaleType.putOFStringArray("US"); + m_RescaleIntercept.putOFStringArray("0"); + m_RescaleSlope.putOFStringArray("1"); + m_RescaleType.putOFStringArray("US"); } - void FGPixelValueTransformation::setUseAsIdentityPixelValueTransformation() { - m_UseAsIdentityPixelValueTransformationFG = OFTrue; + m_fgSubType = E_PixelValTrans_Identity; } +void FGPixelValueTransformation::setFGType(const FGPixelValueTransformation::E_PixelValueTransformationSubType fgType) +{ + m_fgSubType = fgType; +} +FGPixelValueTransformation::E_PixelValueTransformationSubType FGPixelValueTransformation::getFGType() const +{ + return m_fgSubType; +} FGPixelValueTransformation::~FGPixelValueTransformation() { - } - OFCondition FGPixelValueTransformation::check() const { - if (m_UseAsIdentityPixelValueTransformationFG) - { + OFCondition result = EC_Normal; Float64 rs, ri; rs = ri = 0; OFString rt; - OFBool ok = OFTrue; - if (OFconst_cast(DcmDecimalString*, &m_RescaleIntercept)->getFloat64(ri).good()) - { - if (ri != 0) - { - DCMFG_ERROR("Rescale Intercept in Identity Pixel Value Transformation FG must be 0 but is set to " << ri); - ok = OFFalse; - } - } - else - { - DCMFG_ERROR("Invalid or no value for Rescale Intercept in Identity Pixel Value Transformation FG (0 is the only valid value"); - ok = OFFalse; - } - - if (OFconst_cast(DcmDecimalString*, &m_RescaleSlope)->getFloat64(rs).good()) + switch (m_fgSubType) { - if (rs != 1) - { - DCMFG_ERROR("Rescale Slope in Identity Pixel Value Transformation FG must be 1 but is set to " << rs); - ok = OFFalse; - } + case E_PixelValTrans_Identity: + if (OFconst_cast(DcmDecimalString*, &m_RescaleIntercept)->getFloat64(ri).good()) + { + if (ri != 0) + { + DCMFG_ERROR("Rescale Intercept in Identity Pixel Value Transformation FG must be 0 but is set to " + << ri); + result = FG_EC_InvalidData; + } + } + else + { + DCMFG_ERROR( + "Invalid or no value for Rescale Intercept in Identity Pixel Value Transformation FG (0 is the " + "only valid value"); + result = FG_EC_InvalidData; + } + + if (OFconst_cast(DcmDecimalString*, &m_RescaleSlope)->getFloat64(rs).good()) + { + if (rs != 1) + { + DCMFG_ERROR("Rescale Slope in Identity Pixel Value Transformation FG must be 1 but is set to " + << rs); + result = FG_EC_InvalidData; + ; + } + } + else + { + DCMFG_ERROR("Invalid or no value for Rescale Slope in Identity Pixel Value Transformation FG (1 is the " + "only valid value"); + result = FG_EC_InvalidData; + ; + } + + if (OFconst_cast(DcmLongString*, &m_RescaleType)->getOFStringArray(rt).good()) + { + if (rt != "US") + { + DCMFG_ERROR("Rescale Type in Identity Pixel Value Transformation FG must be \"US\" but is set to " + << rt); + result = FG_EC_InvalidData; + ; + } + } + else + { + DCMFG_ERROR( + "Invalid or no value for Rescale Type in Identity Pixel Value Transformation FG (\"US\" is the " + "only valid value"); + result = FG_EC_InvalidData; + ; + } + break; + case E_PixelValTrans_CT: + case E_PixelValTrans_Normal: + default: + // No checks possible + break; } - else - { - DCMFG_ERROR("Invalid or no value for Rescale Slope in Identity Pixel Value Transformation FG (1 is the only valid value"); - ok = OFFalse; - } - - if (OFconst_cast(DcmLongString*, &m_RescaleType)->getOFStringArray(rt).good()) - { - if (rt != "US") - { - DCMFG_ERROR("Rescale Type in Identity Pixel Value Transformation FG must be \"US\" but is set to " << rt); - ok = OFFalse; - } - } - else - { - DCMFG_ERROR("Invalid or no value for Rescale Type in Identity Pixel Value Transformation FG (\"US\" is the only valid value"); - ok = OFFalse; - } - if (!ok) - { - return FG_EC_InvalidData; - } - } - return EC_Normal; + return result; } - void FGPixelValueTransformation::clearData() { - m_RescaleIntercept.clear(); - m_RescaleSlope.clear(); - m_RescaleType.clear(); + m_RescaleIntercept.clear(); + m_RescaleSlope.clear(); + m_RescaleType.clear(); } - FGBase* FGPixelValueTransformation::clone() const { - if(FGPixelValueTransformation* copy = new FGPixelValueTransformation) - { - copy->m_RescaleIntercept = m_RescaleIntercept; - copy->m_RescaleSlope = m_RescaleSlope; - copy->m_RescaleType = m_RescaleType; - return copy; - } - return OFnullptr; + if (FGPixelValueTransformation* copy = new FGPixelValueTransformation) + { + copy->m_RescaleIntercept = m_RescaleIntercept; + copy->m_RescaleSlope = m_RescaleSlope; + copy->m_RescaleType = m_RescaleType; + return copy; + } + return OFnullptr; } - OFCondition FGPixelValueTransformation::read(DcmItem& item) { - clearData(); - - DcmItem* seqItem; - OFCondition result; - - seqItem = OFnullptr; - result = getItemFromFGSequence(item, DCM_PixelValueTransformationSequence, 0, seqItem); - if(result.bad()) - return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleIntercept, "1", "1", "Identity Pixel Value Transformation"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleSlope, "1", "1", "Identity Pixel Value Transformation"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleType, "1", "1", "Identity Pixel Value Transformation"); + clearData(); + + DcmItem* seqItem; + OFCondition result; + + seqItem = OFnullptr; + result = getItemFromFGSequence(item, DCM_PixelValueTransformationSequence, 0, seqItem); + if (result.bad()) + return result; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleIntercept, "1", "1", fgType2Str().c_str()); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleSlope, "1", "1", fgType2Str().c_str()); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RescaleType, "1", "1", fgType2Str().c_str()); + + // Try to guess type of Pixel Value Transformation FG by checking for SOP Class + OFString sopClass; + if (item.getRootItem()->findAndGetOFString(DCM_SOPClassUID, sopClass).good() && !sopClass.empty()) + { + // Identity Pixel Value Transformation FG + if ((sopClass == UID_BreastTomosynthesisImageStorage) + || (sopClass == UID_BreastProjectionXRayImageStorageForPresentation) + || (sopClass == UID_BreastProjectionXRayImageStorageForProcessing) + || (sopClass == UID_ParametricMapStorage)) + + { + DCMFG_DEBUG("FGPixelValueTransformation: Using SOP Class to set Pixel Value Transformation FG to type: " + << fgType2Str()); + m_fgSubType = E_PixelValTrans_Identity; + } + + // CT Pixel Value Transformation FG + else if ((sopClass == UID_EnhancedCTImageStorage) || (sopClass == UID_LegacyConvertedEnhancedCTImageStorage)) + { + m_fgSubType = E_PixelValTrans_CT; + DCMFG_DEBUG("FGPixelValueTransformation: Using SOP Class to set Pixel Value Transformation FG to type: " + << fgType2Str()); + } + else + { + m_fgSubType = E_PixelValTrans_Normal; + DCMFG_DEBUG( + "FGPixelValueTransformation: Setting Pixel Value Transformation FG is of type: " << fgType2Str()); + } + } - return EC_Normal; + return EC_Normal; } - OFCondition FGPixelValueTransformation::write(DcmItem& item) { - DcmItem* seqItem; - DCMFG_DEBUG("Identity Pixel Value Transformation Macro: Fixing values for Rescale Slope, Intercept and Type to enumerated values '1', '0' and 'US'"); - m_RescaleSlope.putOFStringArray("1"); - m_RescaleIntercept.putOFStringArray("0"); - m_RescaleType.putOFStringArray("US"); + DcmItem* seqItem; + if (m_fgSubType == E_PixelValTrans_Identity) + { + DCMFG_DEBUG(fgType2Str() << ": Fixing values for Rescale Slope, Intercept and Type to " + "enumerated values '1', '0' and 'US'"); + m_RescaleSlope.putOFStringArray("1"); + m_RescaleIntercept.putOFStringArray("0"); + m_RescaleType.putOFStringArray("US"); + } - seqItem = OFnullptr; - OFCondition result = createNewFGSequence(item, DCM_PixelValueTransformationSequence, 0, seqItem); - if(result.bad()) - return result; - DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleIntercept, "1", "1", "Identity Pixel Value Transformation"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleSlope, "1", "1", "Identity Pixel Value Transformation"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleType, "1", "1", "Identity Pixel Value Transformation"); + seqItem = OFnullptr; + OFCondition result = createNewFGSequence(item, DCM_PixelValueTransformationSequence, 0, seqItem); + if (result.bad()) + return result; + DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleIntercept, "1", "1", fgType2Str().c_str()); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleSlope, "1", "1", fgType2Str().c_str()); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_RescaleType, "1", "1", fgType2Str().c_str()); - return result; + return result; } - int FGPixelValueTransformation::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if(result == 0) - { - const FGPixelValueTransformation* myRhs = OFstatic_cast(const FGPixelValueTransformation*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_RescaleIntercept.compare(myRhs->m_RescaleIntercept); - if (result == 0) result = m_RescaleSlope.compare(myRhs->m_RescaleSlope); - if (result == 0) result = m_RescaleType.compare(myRhs->m_RescaleType); - } + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGPixelValueTransformation* myRhs = OFstatic_cast(const FGPixelValueTransformation*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_RescaleIntercept.compare(myRhs->m_RescaleIntercept); + if (result == 0) + result = m_RescaleSlope.compare(myRhs->m_RescaleSlope); + if (result == 0) + result = m_RescaleType.compare(myRhs->m_RescaleType); + } - return result; + return result; } - -OFCondition FGPixelValueTransformation::getRescaleIntercept(OFString &value, - const signed long pos) const +OFCondition FGPixelValueTransformation::getRescaleIntercept(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_RescaleIntercept, value, pos); + return DcmIODUtil::getStringValueFromElement(m_RescaleIntercept, value, pos); } - -OFCondition FGPixelValueTransformation::getRescaleSlope(OFString &value, - const signed long pos) const +OFCondition FGPixelValueTransformation::getRescaleSlope(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_RescaleSlope, value, pos); + return DcmIODUtil::getStringValueFromElement(m_RescaleSlope, value, pos); } - -OFCondition FGPixelValueTransformation::getRescaleType(OFString &value, - const signed long pos) const +OFCondition FGPixelValueTransformation::getRescaleType(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_RescaleType, value, pos); + return DcmIODUtil::getStringValueFromElement(m_RescaleType, value, pos); } - -OFCondition FGPixelValueTransformation::setRescaleIntercept(const OFString &value, - const OFBool checkValue) +OFCondition FGPixelValueTransformation::setRescaleIntercept(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_RescaleIntercept.putString(value.c_str()); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_RescaleIntercept.putString(value.c_str()); + return result; } - -OFCondition FGPixelValueTransformation::setRescaleSlope(const OFString &value, - const OFBool checkValue) +OFCondition FGPixelValueTransformation::setRescaleSlope(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_RescaleSlope.putString(value.c_str()); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_RescaleSlope.putString(value.c_str()); + return result; } - -OFCondition FGPixelValueTransformation::setRescaleType(const OFString &value, - const OFBool checkValue) +OFCondition FGPixelValueTransformation::setRescaleType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_RescaleType.putString(value.c_str()); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_RescaleType.putString(value.c_str()); + return result; } +OFString FGPixelValueTransformation::fgType2Str() +{ + OFString result; + switch (m_fgSubType) + { + case E_PixelValTrans_Normal: + result = "Pixel Value Transformation"; + break; + case E_PixelValTrans_Identity: + result = "Identity Pixel Value Transformation"; + break; + case E_PixelValTrans_CT: + result = "CT Pixel Value Transformation"; + break; + default: + DCMFG_WARN("Internal error: Unknown value for enum E_PixelValueTransformationType in fgType2Str(): " + << m_fgSubType); + result = ""; + } + return result; +} diff --git a/dcmfg/libsrc/fgpixmsr.cc b/dcmfg/libsrc/fgpixmsr.cc index 76bb4bb9..61a432af 100644 --- a/dcmfg/libsrc/fgpixmsr.cc +++ b/dcmfg/libsrc/fgpixmsr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,162 +19,144 @@ * */ - #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgpixmsr.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgpixmsr.h" #include "dcmtk/dcmiod/iodutil.h" - FGPixelMeasures::FGPixelMeasures() -: FGBase(DcmFGTypes::EFG_PIXELMEASURES), - m_PixelSpacing(DCM_PixelSpacing), - m_SliceThickness(DCM_SliceThickness), - m_SpacingBetweenSlices(DCM_SpacingBetweenSlices) + : FGBase(DcmFGTypes::EFG_PIXELMEASURES) + , m_PixelSpacing(DCM_PixelSpacing) + , m_SliceThickness(DCM_SliceThickness) + , m_SpacingBetweenSlices(DCM_SpacingBetweenSlices) { } - FGPixelMeasures::~FGPixelMeasures() { - // nothing to do + // nothing to do } - FGBase* FGPixelMeasures::clone() const { - FGPixelMeasures* copy = new FGPixelMeasures(); - if (copy) - { - copy->m_PixelSpacing = this->m_PixelSpacing; - copy->m_SliceThickness = this->m_SliceThickness; - copy->m_SpacingBetweenSlices = this->m_SpacingBetweenSlices; - } - return copy; + FGPixelMeasures* copy = new FGPixelMeasures(); + if (copy) + { + copy->m_PixelSpacing = this->m_PixelSpacing; + copy->m_SliceThickness = this->m_SliceThickness; + copy->m_SpacingBetweenSlices = this->m_SpacingBetweenSlices; + } + return copy; } - void FGPixelMeasures::clearData() { - m_PixelSpacing.clear(); - m_SliceThickness.clear(); - m_SpacingBetweenSlices.clear(); + m_PixelSpacing.clear(); + m_SliceThickness.clear(); + m_SpacingBetweenSlices.clear(); } - OFCondition FGPixelMeasures::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - int FGPixelMeasures::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGPixelMeasures* myRhs = OFstatic_cast(const FGPixelMeasures*, &rhs); - if (!myRhs) - return -1; + const FGPixelMeasures* myRhs = OFstatic_cast(const FGPixelMeasures*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - result = m_PixelSpacing.compare(myRhs->m_PixelSpacing); - if (result == 0) - result = m_SliceThickness.compare(myRhs->m_SliceThickness); - if (result == 0) - result = m_SpacingBetweenSlices.compare(myRhs->m_SpacingBetweenSlices); + // Compare all elements + result = m_PixelSpacing.compare(myRhs->m_PixelSpacing); + if (result == 0) + result = m_SliceThickness.compare(myRhs->m_SliceThickness); + if (result == 0) + result = m_SpacingBetweenSlices.compare(myRhs->m_SpacingBetweenSlices); - return result; + return result; } - /// Read from Frame Content Sequence OFCondition FGPixelMeasures::read(DcmItem& item) { - clearData(); + clearData(); - OFCondition result; - DcmItem* seqItem = NULL; - result = getItemFromFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); - if (result.bad()) - return result; + OFCondition result; + DcmItem* seqItem = NULL; + result = getItemFromFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); + if (result.bad()) + return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); - return EC_Normal; + return EC_Normal; } OFCondition FGPixelMeasures::write(DcmItem& item) { - DcmItem* seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); - return result; + return result; } - -OFCondition FGPixelMeasures::getPixelSpacing(Float64& value, - const signed long pos) +OFCondition FGPixelMeasures::getPixelSpacing(Float64& value, const unsigned long pos) { - return m_PixelSpacing.getFloat64(value, pos); + return m_PixelSpacing.getFloat64(value, pos); } - -OFCondition FGPixelMeasures:: getSliceThickness(Float64& value, - const signed long pos) +OFCondition FGPixelMeasures::getSliceThickness(Float64& value, const unsigned long pos) { - return m_SliceThickness.getFloat64(value, pos); + return m_SliceThickness.getFloat64(value, pos); } - -OFCondition FGPixelMeasures:: getSpacingBetweenSlices(Float64& value, - const signed long pos) +OFCondition FGPixelMeasures::getSpacingBetweenSlices(Float64& value, const unsigned long pos) { - return m_SpacingBetweenSlices.getFloat64(value, pos); + return m_SpacingBetweenSlices.getFloat64(value, pos); } - -OFCondition FGPixelMeasures::setPixelSpacing(const OFString& value, - const OFBool checkValue) +OFCondition FGPixelMeasures::setPixelSpacing(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "2") : EC_Normal; - if (result.good()) - { - result = m_PixelSpacing.putOFStringArray(value); - } - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "2") : EC_Normal; + if (result.good()) + { + result = m_PixelSpacing.putOFStringArray(value); + } + return result; } - -OFCondition FGPixelMeasures::setSliceThickness(const OFString& value, - const OFBool checkValue) +OFCondition FGPixelMeasures::setSliceThickness(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_SliceThickness.putOFStringArray(value); - } - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_SliceThickness.putOFStringArray(value); + } + return result; } -OFCondition FGPixelMeasures::setSpacingBetweenSlices(const OFString& value, - const OFBool checkValue) +OFCondition FGPixelMeasures::setSpacingBetweenSlices(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_SpacingBetweenSlices.putOFStringArray(value); - } - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_SpacingBetweenSlices.putOFStringArray(value); + } + return result; } diff --git a/dcmfg/libsrc/fgplanor.cc b/dcmfg/libsrc/fgplanor.cc index 36a00dca..8bc73606 100644 --- a/dcmfg/libsrc/fgplanor.cc +++ b/dcmfg/libsrc/fgplanor.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,45 +19,41 @@ * */ - #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgplanor.h" -#include "dcmtk/dcmfg/fgfact.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmfg/fgplanor.h" #include "dcmtk/dcmiod/iodutil.h" - -FGPlaneOrientationPatient::FGPlaneOrientationPatient() : - FGBase(DcmFGTypes::EFG_PLANEORIENTPATIENT), - m_ImageOrientationPatient(DCM_ImageOrientationPatient) +FGPlaneOrientationPatient::FGPlaneOrientationPatient() + : FGBase(DcmFGTypes::EFG_PLANEORIENTPATIENT) + , m_ImageOrientationPatient(DCM_ImageOrientationPatient) { } /// clear old values void FGPlaneOrientationPatient::clearData() { - m_ImageOrientationPatient.clear(); + m_ImageOrientationPatient.clear(); } - OFCondition FGPlaneOrientationPatient::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - FGBase* FGPlaneOrientationPatient::clone() const { - FGPlaneOrientationPatient* copy = new FGPlaneOrientationPatient(); - if (copy) - { - copy->m_ImageOrientationPatient = this->m_ImageOrientationPatient; - } - return copy; + FGPlaneOrientationPatient* copy = new FGPlaneOrientationPatient(); + if (copy) + { + copy->m_ImageOrientationPatient = this->m_ImageOrientationPatient; + } + return copy; } - FGPlaneOrientationPatient* FGPlaneOrientationPatient::createMinimal(const OFString& imageOrientationPatientRowX, const OFString& imageOrientationPatientRowY, const OFString& imageOrientationPatientRowZ, @@ -65,99 +61,94 @@ FGPlaneOrientationPatient* FGPlaneOrientationPatient::createMinimal(const OFStri const OFString& imageOrientationPatientColY, const OFString& imageOrientationPatientColZ) { - FGPlaneOrientationPatient *fg = OFstatic_cast(FGPlaneOrientationPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEORIENTPATIENT)); - if (fg) - { - OFCondition result = fg->setImageOrientationPatient(imageOrientationPatientRowX, - imageOrientationPatientRowY, - imageOrientationPatientRowZ, - imageOrientationPatientColX, - imageOrientationPatientColY, - imageOrientationPatientColZ); - if (result.bad()) + FGPlaneOrientationPatient* fg + = OFstatic_cast(FGPlaneOrientationPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEORIENTPATIENT)); + if (fg) { - DCMFG_ERROR("Could not create new FGPlaneOrientationPatient: Invalid data for Image Orientation Patient: " << result.text()); - delete fg; - return NULL; + OFCondition result = fg->setImageOrientationPatient(imageOrientationPatientRowX, + imageOrientationPatientRowY, + imageOrientationPatientRowZ, + imageOrientationPatientColX, + imageOrientationPatientColY, + imageOrientationPatientColZ); + if (result.bad()) + { + DCMFG_ERROR("Could not create new FGPlaneOrientationPatient: Invalid data for Image Orientation Patient: " + << result.text()); + delete fg; + return NULL; + } } - } - return fg; + return fg; } - - /// Read from Plane Position Sequence OFCondition FGPlaneOrientationPatient::read(DcmItem& item) { - clearData(); + clearData(); - DcmItem *seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); + if (result.bad()) + return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); - return EC_Normal; + return EC_Normal; } - OFCondition FGPlaneOrientationPatient::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write plane position (patient) attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); + // --- write plane position (patient) attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); - return result; + return result; } - - int FGPlaneOrientationPatient::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result == 0) - { - const FGPlaneOrientationPatient* myRhs = OFstatic_cast(const FGPlaneOrientationPatient*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_ImageOrientationPatient.compare(myRhs->m_ImageOrientationPatient); - } - - return result; -} - + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGPlaneOrientationPatient* myRhs = OFstatic_cast(const FGPlaneOrientationPatient*, &rhs); + if (!myRhs) + return -1; -OFCondition FGPlaneOrientationPatient::getImageOrientationPatient(OFString& value, - const signed long pos = 0) + // Compare all elements + result = m_ImageOrientationPatient.compare(myRhs->m_ImageOrientationPatient); + } -{ - return DcmIODUtil::getStringValueFromElement(m_ImageOrientationPatient, value, pos); + return result; } +OFCondition FGPlaneOrientationPatient::getImageOrientationPatient(OFString& value, const signed long pos = 0) -OFCondition FGPlaneOrientationPatient::getImageOrientationPatient(Float64& rowX, - Float64& rowY, - Float64& rowZ, - Float64& colX, - Float64& colY, - Float64& colZ) { - OFCondition result = m_ImageOrientationPatient.getFloat64(rowX, 0); - if (result.good()) m_ImageOrientationPatient.getFloat64(rowY, 1); - if (result.good()) m_ImageOrientationPatient.getFloat64(rowZ, 2); - if (result.good()) m_ImageOrientationPatient.getFloat64(colX, 3); - if (result.good()) m_ImageOrientationPatient.getFloat64(colY, 4); - if (result.good()) m_ImageOrientationPatient.getFloat64(colZ, 5); - return result; + return DcmIODUtil::getStringValueFromElement(m_ImageOrientationPatient, value, pos); } +OFCondition FGPlaneOrientationPatient::getImageOrientationPatient( + Float64& rowX, Float64& rowY, Float64& rowZ, Float64& colX, Float64& colY, Float64& colZ) +{ + OFCondition result = m_ImageOrientationPatient.getFloat64(rowX, 0); + if (result.good()) + m_ImageOrientationPatient.getFloat64(rowY, 1); + if (result.good()) + m_ImageOrientationPatient.getFloat64(rowZ, 2); + if (result.good()) + m_ImageOrientationPatient.getFloat64(colX, 3); + if (result.good()) + m_ImageOrientationPatient.getFloat64(colY, 4); + if (result.good()) + m_ImageOrientationPatient.getFloat64(colZ, 5); + return result; +} OFCondition FGPlaneOrientationPatient::setImageOrientationPatient(const OFString& rowX, const OFString& rowY, @@ -167,21 +158,25 @@ OFCondition FGPlaneOrientationPatient::setImageOrientationPatient(const OFString const OFString& colZ, const OFBool checkValue) { - OFString str(rowX); str += "\\"; - str += rowY; str += "\\"; - str += rowZ; str += "\\"; - str += colX; str += "\\"; - str += colY; str += "\\"; - str += colZ; - - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "6") : EC_Normal; - if (result.good()) - result = m_ImageOrientationPatient.putOFStringArray(str); - return result; + OFString str(rowX); + str += "\\"; + str += rowY; + str += "\\"; + str += rowZ; + str += "\\"; + str += colX; + str += "\\"; + str += colY; + str += "\\"; + str += colZ; + + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "6") : EC_Normal; + if (result.good()) + result = m_ImageOrientationPatient.putOFStringArray(str); + return result; } - FGPlaneOrientationPatient::~FGPlaneOrientationPatient() { - // nothing to do + // nothing to do } diff --git a/dcmfg/libsrc/fgplanorvol.cc b/dcmfg/libsrc/fgplanorvol.cc index c7d41171..71ec08e5 100644 --- a/dcmfg/libsrc/fgplanorvol.cc +++ b/dcmfg/libsrc/fgplanorvol.cc @@ -20,81 +20,72 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmdata/dcvrfd.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmdata/dcvrfd.h" #include "dcmtk/dcmfg/fgplanorvol.h" #include "dcmtk/dcmfg/fgtypes.h" - +#include "dcmtk/dcmiod/iodutil.h" // Constructor -FGPlaneOrientationVolume::FGPlaneOrientationVolume() : - FGBase(DcmFGTypes::EFG_PLANEORIENTVOLUME), - m_ImageOrientationVolume(DCM_ImageOrientationVolume) +FGPlaneOrientationVolume::FGPlaneOrientationVolume() + : FGBase(DcmFGTypes::EFG_PLANEORIENTVOLUME) + , m_ImageOrientationVolume(DCM_ImageOrientationVolume) { } - FGPlaneOrientationVolume::~FGPlaneOrientationVolume() { - // nothing to do + // nothing to do } - FGBase* FGPlaneOrientationVolume::clone() const { - FGPlaneOrientationVolume* copy = new FGPlaneOrientationVolume(); - if (copy) - { - copy->m_ImageOrientationVolume = this->m_ImageOrientationVolume; - } - return copy; + FGPlaneOrientationVolume* copy = new FGPlaneOrientationVolume(); + if (copy) + { + copy->m_ImageOrientationVolume = this->m_ImageOrientationVolume; + } + return copy; } - void FGPlaneOrientationVolume::clearData() { - m_ImageOrientationVolume.clear(); + m_ImageOrientationVolume.clear(); } - OFCondition FGPlaneOrientationVolume::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - // --- get() functionality --- -OFCondition FGPlaneOrientationVolume::getImageOrientationVolume(Float64& value, - const long unsigned int pos) +OFCondition FGPlaneOrientationVolume::getImageOrientationVolume(Float64& value, const long unsigned int pos) { - return m_ImageOrientationVolume.getFloat64(value, pos); + return m_ImageOrientationVolume.getFloat64(value, pos); } - - -OFCondition FGPlaneOrientationVolume::getImageOrientationVolume(Float64& rowX, - Float64& rowY, - Float64& rowZ, - Float64& colX, - Float64& colY, - Float64& colZ) +OFCondition FGPlaneOrientationVolume::getImageOrientationVolume( + Float64& rowX, Float64& rowY, Float64& rowZ, Float64& colX, Float64& colY, Float64& colZ) { - OFCondition result = m_ImageOrientationVolume.getFloat64(rowX, 0); - if (result.good()) result = m_ImageOrientationVolume.getFloat64(rowY, 1); - if (result.good()) result = m_ImageOrientationVolume.getFloat64(rowZ, 2); - if (result.good()) result = m_ImageOrientationVolume.getFloat64(colX, 3); - if (result.good()) result = m_ImageOrientationVolume.getFloat64(colY, 4); - if (result.good()) result = m_ImageOrientationVolume.getFloat64(colZ, 5); - return result; + OFCondition result = m_ImageOrientationVolume.getFloat64(rowX, 0); + if (result.good()) + result = m_ImageOrientationVolume.getFloat64(rowY, 1); + if (result.good()) + result = m_ImageOrientationVolume.getFloat64(rowZ, 2); + if (result.good()) + result = m_ImageOrientationVolume.getFloat64(colX, 3); + if (result.good()) + result = m_ImageOrientationVolume.getFloat64(colY, 4); + if (result.good()) + result = m_ImageOrientationVolume.getFloat64(colZ, 5); + return result; } - // --- set() functionality --- - OFCondition FGPlaneOrientationVolume::setImageOrientationVolume(const Float64& rowX, const Float64& rowY, const Float64& rowZ, @@ -103,60 +94,59 @@ OFCondition FGPlaneOrientationVolume::setImageOrientationVolume(const Float64& r const Float64& colZ, const OFBool) { - OFCondition result = m_ImageOrientationVolume.putFloat64(rowX, 0); - if (result.good()) m_ImageOrientationVolume.putFloat64(rowY, 1); - if (result.good()) m_ImageOrientationVolume.putFloat64(rowZ, 2); - if (result.good()) m_ImageOrientationVolume.putFloat64(colX, 3); - if (result.good()) m_ImageOrientationVolume.putFloat64(colY, 4); - if (result.good()) m_ImageOrientationVolume.putFloat64(colZ, 5); - return result; + OFCondition result = m_ImageOrientationVolume.putFloat64(rowX, 0); + if (result.good()) + m_ImageOrientationVolume.putFloat64(rowY, 1); + if (result.good()) + m_ImageOrientationVolume.putFloat64(rowZ, 2); + if (result.good()) + m_ImageOrientationVolume.putFloat64(colX, 3); + if (result.good()) + m_ImageOrientationVolume.putFloat64(colY, 4); + if (result.good()) + m_ImageOrientationVolume.putFloat64(colZ, 5); + return result; } - /// Read Plane Orientation (Volume) Sequence from given item OFCondition FGPlaneOrientationVolume::read(DcmItem& item) { - clearData(); + clearData(); - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); - if (result.bad()) - return result; - - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); + if (result.bad()) + return result; - return EC_Normal; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); + return EC_Normal; } /// Writes single Plane Orientation (Volume) Sequence into given item OFCondition FGPlaneOrientationVolume::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); - return result; + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); + return result; } - int FGPlaneOrientationVolume::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGPlaneOrientationVolume* myRhs = OFstatic_cast(const FGPlaneOrientationVolume*, &rhs); - if (!myRhs) - return -1; + const FGPlaneOrientationVolume* myRhs = OFstatic_cast(const FGPlaneOrientationVolume*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - result = m_ImageOrientationVolume.compare(myRhs->m_ImageOrientationVolume); - return result; + // Compare all elements + result = m_ImageOrientationVolume.compare(myRhs->m_ImageOrientationVolume); + return result; } - - - diff --git a/dcmfg/libsrc/fgplanpo.cc b/dcmfg/libsrc/fgplanpo.cc index b1c46109..cc225792 100644 --- a/dcmfg/libsrc/fgplanpo.cc +++ b/dcmfg/libsrc/fgplanpo.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,129 +20,121 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgplanpo.h" -#include "dcmtk/dcmfg/fgfact.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmfg/fgplanpo.h" #include "dcmtk/dcmiod/iodutil.h" -FGPlanePosPatient::FGPlanePosPatient() : - FGBase(DcmFGTypes::EFG_PLANEPOSPATIENT), - m_ImagePositionPatient(DCM_ImagePositionPatient) +FGPlanePosPatient::FGPlanePosPatient() + : FGBase(DcmFGTypes::EFG_PLANEPOSPATIENT) + , m_ImagePositionPatient(DCM_ImagePositionPatient) { } FGBase* FGPlanePosPatient::clone() const { - FGPlanePosPatient* copy = new FGPlanePosPatient(); - if (copy) - { - copy->m_ImagePositionPatient = this->m_ImagePositionPatient; - } - return copy; + FGPlanePosPatient* copy = new FGPlanePosPatient(); + if (copy) + { + copy->m_ImagePositionPatient = this->m_ImagePositionPatient; + } + return copy; } - FGPlanePosPatient* FGPlanePosPatient::createMinimal(const OFString& imagePositionPatientX, const OFString& imagePositionPatientY, const OFString& imagePositionPatientZ) { - FGPlanePosPatient *fg = OFstatic_cast(FGPlanePosPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEPOSPATIENT)); - if (fg) - { - OFCondition result = fg->setImagePositionPatient(imagePositionPatientX, imagePositionPatientY, imagePositionPatientZ); - if (result.bad()) + FGPlanePosPatient* fg + = OFstatic_cast(FGPlanePosPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEPOSPATIENT)); + if (fg) { - DCMFG_ERROR("Could not create new FGPlanePosPatient: Invalid data for Image Position Patient: " << result.text()); - delete fg; - return NULL; + OFCondition result + = fg->setImagePositionPatient(imagePositionPatientX, imagePositionPatientY, imagePositionPatientZ); + if (result.bad()) + { + DCMFG_ERROR( + "Could not create new FGPlanePosPatient: Invalid data for Image Position Patient: " << result.text()); + delete fg; + return NULL; + } } - } - return fg; + return fg; } - - /// clear old values void FGPlanePosPatient::clearData() { - m_ImagePositionPatient.clear(); + m_ImagePositionPatient.clear(); } - OFCondition FGPlanePosPatient::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - /// Read from Plane Position Sequence OFCondition FGPlanePosPatient::read(DcmItem& item) { - clearData(); + clearData(); - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); + if (result.bad()) + return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); - return EC_Normal; + return EC_Normal; } - OFCondition FGPlanePosPatient::write(DcmItem& item) { - DcmItem* seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write plane position (patient) attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); + // --- write plane position (patient) attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); - return result; + return result; } - int FGPlanePosPatient::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result == 0) - { - const FGPlanePosPatient* myRhs = OFstatic_cast(const FGPlanePosPatient*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_ImagePositionPatient.compare(myRhs->m_ImagePositionPatient); - } - - return result; -} + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGPlanePosPatient* myRhs = OFstatic_cast(const FGPlanePosPatient*, &rhs); + if (!myRhs) + return -1; + // Compare all elements + result = m_ImagePositionPatient.compare(myRhs->m_ImagePositionPatient); + } + return result; +} -OFCondition FGPlanePosPatient::getImagePositionPatient(OFString& value, - const signed long pos = 0) +OFCondition FGPlanePosPatient::getImagePositionPatient(OFString& value, const signed long pos = 0) { - return DcmIODUtil::getStringValueFromElement(m_ImagePositionPatient, value, pos); + return DcmIODUtil::getStringValueFromElement(m_ImagePositionPatient, value, pos); } - -OFCondition FGPlanePosPatient::getImagePositionPatient(Float64& coordinateX, - Float64& coordinateY, - Float64& coordinateZ) +OFCondition FGPlanePosPatient::getImagePositionPatient(Float64& coordinateX, Float64& coordinateY, Float64& coordinateZ) { - OFCondition result = m_ImagePositionPatient.getFloat64(coordinateX, 0); - if (result.good()) result = m_ImagePositionPatient.getFloat64(coordinateY, 1); - if (result.good()) result = m_ImagePositionPatient.getFloat64(coordinateZ, 2); - return result; + OFCondition result = m_ImagePositionPatient.getFloat64(coordinateX, 0); + if (result.good()) + result = m_ImagePositionPatient.getFloat64(coordinateY, 1); + if (result.good()) + result = m_ImagePositionPatient.getFloat64(coordinateZ, 2); + return result; } - OFCondition FGPlanePosPatient::setImagePositionPatient(const OFString& coordinateX, const OFString& coordinateY, const OFString& coordinateZ, @@ -150,19 +142,18 @@ OFCondition FGPlanePosPatient::setImagePositionPatient(const OFString& coordinat { - OFString str(coordinateX); - str += "\\"; - str += coordinateY; - str += "\\"; - str += coordinateZ; - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "3") : EC_Normal; - if (result.good()) - result = m_ImagePositionPatient.putOFStringArray(str); - return result; + OFString str(coordinateX); + str += "\\"; + str += coordinateY; + str += "\\"; + str += coordinateZ; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "3") : EC_Normal; + if (result.good()) + result = m_ImagePositionPatient.putOFStringArray(str); + return result; } - FGPlanePosPatient::~FGPlanePosPatient() { - // nothing to do + // nothing to do } diff --git a/dcmfg/libsrc/fgplanposvol.cc b/dcmfg/libsrc/fgplanposvol.cc index 70e650a4..1980fd8b 100644 --- a/dcmfg/libsrc/fgplanposvol.cc +++ b/dcmfg/libsrc/fgplanposvol.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,136 +20,127 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/fgplanposvol.h" #include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodutil.h" // Constructor -FGPlanePositionVolume::FGPlanePositionVolume() : - FGBase(DcmFGTypes::EFG_PLANEPOSITIONVOLUME), - m_ImagePositionVolume(DCM_ImagePositionVolume) +FGPlanePositionVolume::FGPlanePositionVolume() + : FGBase(DcmFGTypes::EFG_PLANEPOSITIONVOLUME) + , m_ImagePositionVolume(DCM_ImagePositionVolume) { } - FGPlanePositionVolume::~FGPlanePositionVolume() { - // nothing to do + // nothing to do } - FGBase* FGPlanePositionVolume::clone() const { - FGPlanePositionVolume* copy = new FGPlanePositionVolume(); - if (copy) - { - copy->m_ImagePositionVolume = this->m_ImagePositionVolume; - } - return copy; + FGPlanePositionVolume* copy = new FGPlanePositionVolume(); + if (copy) + { + copy->m_ImagePositionVolume = this->m_ImagePositionVolume; + } + return copy; } - void FGPlanePositionVolume::clearData() { - m_ImagePositionVolume.clear(); + m_ImagePositionVolume.clear(); } - OFCondition FGPlanePositionVolume::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - // --- get() functionality --- -OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& value, - const long unsigned int pos) +OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& value, const long unsigned int pos) { - return m_ImagePositionVolume.getFloat64(value, pos); + return m_ImagePositionVolume.getFloat64(value, pos); } - -OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& valueX, - Float64& valueY, - Float64& valueZ) +OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& valueX, Float64& valueY, Float64& valueZ) { - OFCondition result = m_ImagePositionVolume.getFloat64(valueX, 0); - if (result.good()) result = m_ImagePositionVolume.getFloat64(valueY, 1); - if (result.good()) result = m_ImagePositionVolume.getFloat64(valueZ, 2); - return result; + OFCondition result = m_ImagePositionVolume.getFloat64(valueX, 0); + if (result.good()) + result = m_ImagePositionVolume.getFloat64(valueY, 1); + if (result.good()) + result = m_ImagePositionVolume.getFloat64(valueZ, 2); + return result; } - OFCondition FGPlanePositionVolume::setImagePositionVolume(const Float64& valueX, const Float64& valueY, const Float64& valueZ, const OFBool checkValue) { - (void)checkValue; - OFCondition result = m_ImagePositionVolume.putFloat64(valueX, 0); - if (result.good()) result = m_ImagePositionVolume.putFloat64(valueY, 1); - if (result.good()) result = m_ImagePositionVolume.putFloat64(valueZ, 2); - return result; + (void)checkValue; + OFCondition result = m_ImagePositionVolume.putFloat64(valueX, 0); + if (result.good()) + result = m_ImagePositionVolume.putFloat64(valueY, 1); + if (result.good()) + result = m_ImagePositionVolume.putFloat64(valueZ, 2); + return result; } - OFCondition FGPlanePositionVolume::setImagePositionVolume(const Float64& value, const long unsigned int pos, const OFBool checkValue) { - // no checks - (void)checkValue; - if (pos > 2) - return EC_ValueMultiplicityViolated; + // no checks + (void)checkValue; + if (pos > 2) + return EC_ValueMultiplicityViolated; - return m_ImagePositionVolume.putFloat64(value, pos); + return m_ImagePositionVolume.putFloat64(value, pos); } - /// Read Plane Position (Volume) Sequence from given item OFCondition FGPlanePositionVolume::read(DcmItem& item) { - clearData(); - - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); - if (result.bad()) - return result; + clearData(); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); + if (result.bad()) + return result; - return EC_Normal; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); + return EC_Normal; } /// Writes single Plane Position (Volume) Sequence into given item OFCondition FGPlanePositionVolume::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); - return result; + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); + return result; } - int FGPlanePositionVolume::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGPlanePositionVolume* myRhs = OFstatic_cast(const FGPlanePositionVolume*, &rhs); - if (!myRhs) - return -1; + const FGPlanePositionVolume* myRhs = OFstatic_cast(const FGPlanePositionVolume*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - result = m_ImagePositionVolume.compare(myRhs->m_ImagePositionVolume); - return result; + // Compare all elements + result = m_ImagePositionVolume.compare(myRhs->m_ImagePositionVolume); + return result; } diff --git a/dcmfg/libsrc/fgrealworldvaluemapping.cc b/dcmfg/libsrc/fgrealworldvaluemapping.cc index b876b39b..e5e8b19b 100644 --- a/dcmfg/libsrc/fgrealworldvaluemapping.cc +++ b/dcmfg/libsrc/fgrealworldvaluemapping.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,458 +20,446 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" #include "dcmtk/dcmiod/iodutil.h" const OFString FGRealWorldValueMapping::RWVMItem::m_ModuleName = "RealWorldValueMappingItemMacro"; FGRealWorldValueMapping::FGRealWorldValueMapping() -: FGBase(DcmFGTypes::EFG_REALWORLDVALUEMAPPING), - m_Items() + : FGBase(DcmFGTypes::EFG_REALWORLDVALUEMAPPING) + , m_Items() { } - FGRealWorldValueMapping::~FGRealWorldValueMapping() { - clearData(); + clearData(); } - FGBase* FGRealWorldValueMapping::clone() const { - FGRealWorldValueMapping* copy = new FGRealWorldValueMapping(); - if (copy) - { - for (OFVector::const_iterator it = m_Items.begin(); it < m_Items.end(); it++) + FGRealWorldValueMapping* copy = new FGRealWorldValueMapping(); + if (copy) { - if (*it == NULL) return NULL; - FGRealWorldValueMapping::RWVMItem* item = (*it)->clone(); - if (item == NULL) return NULL; - copy->m_Items.push_back(item); + for (OFVector::const_iterator it = m_Items.begin(); it < m_Items.end(); + it++) + { + if (*it == NULL) + return NULL; + FGRealWorldValueMapping::RWVMItem* item = (*it)->clone(); + if (item == NULL) + return NULL; + copy->m_Items.push_back(item); + } } - } - return copy; + return copy; } - void FGRealWorldValueMapping::clearData() { - DcmIODUtil::freeContainer(m_Items); + DcmIODUtil::freeContainer(m_Items); } - OFCondition FGRealWorldValueMapping::check() const { - // More checks checks for 1C conditions could be added - return EC_Normal; + // More checks checks for 1C conditions could be added + return EC_Normal; } - int FGRealWorldValueMapping::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGRealWorldValueMapping* myRhs = OFstatic_cast(const FGRealWorldValueMapping*, &rhs); - if (!myRhs) - return -1; + const FGRealWorldValueMapping* myRhs = OFstatic_cast(const FGRealWorldValueMapping*, &rhs); + if (!myRhs) + return -1; - // Compare all items, start with VM - if (m_Items.size() < myRhs->m_Items.size()) - return 1; - else if (m_Items.size() > myRhs->m_Items.size()) - return -1; + // Compare all items, start with VM + if (m_Items.size() < myRhs->m_Items.size()) + return 1; + else if (m_Items.size() > myRhs->m_Items.size()) + return -1; - for (size_t n = 0; m_Items.size(); n++) - { - result = m_Items[n]->compare( *(myRhs->m_Items[n]) ); - if (result != 0) return result; - } - return result; + for (size_t n = 0; m_Items.size(); n++) + { + result = m_Items[n]->compare(*(myRhs->m_Items[n])); + if (result != 0) + return result; + } + return result; } - /// Read from Frame Content Sequence OFCondition FGRealWorldValueMapping::read(DcmItem& item) { - clearData(); + clearData(); - DcmIODUtil::readSubSequence(item, DCM_RealWorldValueMappingSequence, m_Items, "1-n", "1", "RealWorldValueMappingMacro"); + DcmIODUtil::readSubSequence( + item, DCM_RealWorldValueMappingSequence, m_Items, "1-n", "1", "RealWorldValueMappingMacro"); - return EC_Normal; + return EC_Normal; } OFCondition FGRealWorldValueMapping::write(DcmItem& item) { - // OFCondition result = createNewFGSequence(item, DCM_RealWorldValueMappingSequence, 0, seqItem); - OFCondition result; - DcmIODUtil::writeSubSequence(result, DCM_RealWorldValueMappingSequence, m_Items, item, "1-n", "1", "RealWorldValueMappingMacro"); - return result; + // OFCondition result = createNewFGSequence(item, DCM_RealWorldValueMappingSequence, 0, seqItem); + OFCondition result; + DcmIODUtil::writeSubSequence( + result, DCM_RealWorldValueMappingSequence, m_Items, item, "1-n", "1", "RealWorldValueMappingMacro"); + return result; } - -OFVector< FGRealWorldValueMapping::RWVMItem* >& FGRealWorldValueMapping::getRealWorldValueMapping() +OFVector& FGRealWorldValueMapping::getRealWorldValueMapping() { - return m_Items; + return m_Items; } - // ----------------------------------------------------------- - FGRealWorldValueMapping::RWVMItem::RWVMItem(IODComponent* parent) -: IODComponent(parent), - m_MeasurementUnitsCode(), - m_QuantityDefinitionSequence() + : IODComponent(parent) + , m_MeasurementUnitsCode() + , m_QuantityDefinitionSequence() { - resetRules(); + resetRules(); } - -FGRealWorldValueMapping::RWVMItem::RWVMItem(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, +FGRealWorldValueMapping::RWVMItem::RWVMItem(OFshared_ptr item, + OFshared_ptr rules, IODComponent* parent) -: IODComponent(item, rules, parent), - m_MeasurementUnitsCode(), - m_QuantityDefinitionSequence() + : IODComponent(item, rules, parent) + , m_MeasurementUnitsCode() + , m_QuantityDefinitionSequence() { - resetRules(); + resetRules(); } - FGRealWorldValueMapping::RWVMItem::RWVMItem(const FGRealWorldValueMapping::RWVMItem& rhs) -: IODComponent(rhs), - m_MeasurementUnitsCode(rhs.m_MeasurementUnitsCode), - m_QuantityDefinitionSequence() -{ - OFVector::const_iterator it = rhs.m_QuantityDefinitionSequence.begin(); - while (it != rhs.m_QuantityDefinitionSequence.end()) - { - ContentItemMacro* macro = new ContentItemMacro(**it); - if (macro == NULL) + : IODComponent(rhs) + , m_MeasurementUnitsCode(rhs.m_MeasurementUnitsCode) + , m_QuantityDefinitionSequence() +{ + OFVector::const_iterator it = rhs.m_QuantityDefinitionSequence.begin(); + while (it != rhs.m_QuantityDefinitionSequence.end()) { - DCMFG_ERROR("Out of memory in copy constructor of FGRealWorldValueMapping::RWVMItem::RWVMItem"); - return; + ContentItemMacro* macro = new ContentItemMacro(**it); + if (macro == NULL) + { + DCMFG_ERROR("Out of memory in copy constructor of FGRealWorldValueMapping::RWVMItem::RWVMItem"); + return; + } + m_QuantityDefinitionSequence.push_back(macro); + it++; } - m_QuantityDefinitionSequence.push_back(macro); - it++; - } } - - FGRealWorldValueMapping::RWVMItem* FGRealWorldValueMapping::RWVMItem::clone() { - return new FGRealWorldValueMapping::RWVMItem(*this); + return new FGRealWorldValueMapping::RWVMItem(*this); } - - FGRealWorldValueMapping::RWVMItem::~RWVMItem() { - DcmIODUtil::freeContainer(m_QuantityDefinitionSequence); + DcmIODUtil::freeContainer(m_QuantityDefinitionSequence); } - OFString FGRealWorldValueMapping::RWVMItem::getName() const { - return m_ModuleName; + return m_ModuleName; } - int FGRealWorldValueMapping::RWVMItem::compare(const IODComponent& rhs) const { - int result = IODComponent::compare(rhs); - const FGRealWorldValueMapping::RWVMItem* myRhs = OFstatic_cast(const FGRealWorldValueMapping::RWVMItem*, &rhs); - if (!myRhs) - return -1; - - if (result == 0) result = m_MeasurementUnitsCode.compare(*myRhs); - if (result == 0) - { - size_t rhsSize = myRhs->m_QuantityDefinitionSequence.size(); - size_t thisSize = m_QuantityDefinitionSequence.size(); - if (thisSize < rhsSize) - return -1; - else if (thisSize > rhsSize) - return 1; - - OFVector::const_iterator it = m_QuantityDefinitionSequence.begin(); - OFVector::const_iterator rhsIt = myRhs->m_QuantityDefinitionSequence.begin(); - while (it != m_QuantityDefinitionSequence.end() && (result == 0)) + int result = IODComponent::compare(rhs); + const FGRealWorldValueMapping::RWVMItem* myRhs = OFstatic_cast(const FGRealWorldValueMapping::RWVMItem*, &rhs); + if (!myRhs) + return -1; + + if (result == 0) + result = m_MeasurementUnitsCode.compare(*myRhs); + if (result == 0) { - result = (*it)->compare( *(*rhsIt) ); - it++; + size_t rhsSize = myRhs->m_QuantityDefinitionSequence.size(); + size_t thisSize = m_QuantityDefinitionSequence.size(); + if (thisSize < rhsSize) + return -1; + else if (thisSize > rhsSize) + return 1; + + OFVector::const_iterator it = m_QuantityDefinitionSequence.begin(); + OFVector::const_iterator rhsIt = myRhs->m_QuantityDefinitionSequence.begin(); + while (it != m_QuantityDefinitionSequence.end() && (result == 0)) + { + result = (*it)->compare(*(*rhsIt)); + it++; + } } - } - return result; - + return result; } - void FGRealWorldValueMapping::RWVMItem::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_RealWorldValueFirstValueMapped, "1","1C",getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RealWorldValueLastValueMapped, "1","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DoubleFloatRealWorldValueFirstValueMapped, "1","1C",getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DoubleFloatRealWorldValueLastValueMapped, "1","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RealWorldValueIntercept, "1","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RealWorldValueSlope, "1","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RealWorldValueLUTData, "1-n","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LUTExplanation, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LUTLabel, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_QuantityDefinitionSequence, "1-n","3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_RealWorldValueFirstValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueLastValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule( + new IODRule(DCM_DoubleFloatRealWorldValueFirstValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule( + new IODRule(DCM_DoubleFloatRealWorldValueLastValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueIntercept, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueSlope, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueLUTData, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LUTExplanation, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LUTLabel, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_QuantityDefinitionSequence, "1-n", "3", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); +} + +OFCondition FGRealWorldValueMapping::RWVMItem::read(DcmItem& source, const OFBool clearOldData) +{ + DcmIODUtil::readSingleItem(source, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, "1", m_ModuleName); + DcmIODUtil::readSubSequence(source, + DCM_QuantityDefinitionSequence, + m_QuantityDefinitionSequence, + m_Rules->getByTag(DCM_QuantityDefinitionSequence)); + return IODComponent::read(source, clearOldData); } - -OFCondition FGRealWorldValueMapping::RWVMItem::read(DcmItem& source, - const OFBool clearOldData) -{ - DcmIODUtil::readSingleItem(source, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, "1", m_ModuleName); - DcmIODUtil::readSubSequence(source, DCM_QuantityDefinitionSequence, m_QuantityDefinitionSequence, m_Rules->getByTag(DCM_QuantityDefinitionSequence)); - return IODComponent::read(source, clearOldData); -} - - OFCondition FGRealWorldValueMapping::RWVMItem::write(DcmItem& destination) { - OFCondition result; - DcmIODUtil::writeSingleItem(result, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, *m_Item, "1", m_ModuleName); - DcmIODUtil::writeSubSequence(result, DCM_QuantityDefinitionSequence, m_QuantityDefinitionSequence, *m_Item, m_Rules->getByTag(DCM_QuantityDefinitionSequence)); - if (result.good()) result = IODComponent::write(destination); - return result; + OFCondition result; + DcmIODUtil::writeSingleItem( + result, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, *m_Item, "1", m_ModuleName); + DcmIODUtil::writeSubSequence(result, + DCM_QuantityDefinitionSequence, + m_QuantityDefinitionSequence, + *m_Item, + m_Rules->getByTag(DCM_QuantityDefinitionSequence)); + if (result.good()) + result = IODComponent::write(destination); + return result; } - OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueFirstValueMapped(Sint32& value, const unsigned long pos) const { - return getUSorSS(*m_Item, DCM_RealWorldValueFirstValueMapped, pos, value); + return getUSorSS(*m_Item, DCM_RealWorldValueFirstValueMapped, pos, value); } - OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLastValueMapped(Sint32& value, const unsigned long pos) const { - return getUSorSS(*m_Item, DCM_RealWorldValueLastValueMapped, pos, value); + return getUSorSS(*m_Item, DCM_RealWorldValueLastValueMapped, pos, value); } - -OFCondition FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueFirstValueMapped(Float64& value, - const unsigned long pos) const +OFCondition +FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueFirstValueMapped(Float64& value, + const unsigned long pos) const { - return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); + return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); } - -OFCondition FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueLastValueMapped(Float64& value, - const unsigned long pos) const +OFCondition +FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueLastValueMapped(Float64& value, + const unsigned long pos) const { - return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); + return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); } - -OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(OFVector< Float64 >& values) const +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(OFVector& values) const { - DcmElement* elem = NULL; - OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); - if (result.good()) - { - size_t numValues = elem->getNumberOfValues(); - for (size_t n = 0; n < numValues; n++) + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); + if (result.good()) { - Float64 value; - result = elem->getFloat64(value, OFstatic_cast(unsigned long, n)); - if (result.good()) values.push_back(value); + size_t numValues = elem->getNumberOfValues(); + for (size_t n = 0; n < numValues; n++) + { + Float64 value; + result = elem->getFloat64(value, OFstatic_cast(unsigned long, n)); + if (result.good()) + values.push_back(value); + } } - } - return result; + return result; } - -OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(Float64& value, - const unsigned long pos) const +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(Float64& value, const unsigned long pos) const { - return m_Item->findAndGetFloat64(DCM_RealWorldValueLUTData, value, pos); + return m_Item->findAndGetFloat64(DCM_RealWorldValueLUTData, value, pos); } - -OFCondition FGRealWorldValueMapping::RWVMItem::getLUTExplanation(OFString& value, - const signed long pos) const +OFCondition FGRealWorldValueMapping::RWVMItem::getLUTExplanation(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_LUTExplanation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LUTExplanation, *m_Item, value, pos); } - -OFCondition FGRealWorldValueMapping::RWVMItem::getLUTLabel(OFString& value, - const signed long pos) const +OFCondition FGRealWorldValueMapping::RWVMItem::getLUTLabel(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_LUTLabel, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LUTLabel, *m_Item, value, pos); } - CodeSequenceMacro& FGRealWorldValueMapping::RWVMItem::getMeasurementUnitsCode() { - return m_MeasurementUnitsCode; + return m_MeasurementUnitsCode; } - -OFVector & FGRealWorldValueMapping::RWVMItem::getEntireQuantityDefinitionSequence() +OFVector& FGRealWorldValueMapping::RWVMItem::getEntireQuantityDefinitionSequence() { - return m_QuantityDefinitionSequence; + return m_QuantityDefinitionSequence; } - OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappedUnsigned(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueFirstValueMapped); - OFCondition result = us->putUint16(value); - if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); - if (result.bad()) delete us; - return result; + (void)checkValue; + DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueFirstValueMapped); + OFCondition result = us->putUint16(value); + if (result.good()) + result = m_Item->insert(us, OFTrue /* replace old */); + if (result.bad()) + delete us; + return result; } - OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappedSigned(const Sint16& value, const OFBool checkValue) { - (void)checkValue; - DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueFirstValueMapped); - OFCondition result = ss->putSint16(value); - if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); - if (result.bad()) delete ss; - return result; + (void)checkValue; + DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueFirstValueMapped); + OFCondition result = ss->putSint16(value); + if (result.good()) + result = m_Item->insert(ss, OFTrue /* replace old */); + if (result.bad()) + delete ss; + return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedSigned(const Sint16& value, const OFBool checkValue) { - (void)checkValue; - DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueLastValueMapped); - OFCondition result = ss->putSint16(value); - if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); - if (result.bad()) delete ss; - return result; - + (void)checkValue; + DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueLastValueMapped); + OFCondition result = ss->putSint16(value); + if (result.good()) + result = m_Item->insert(ss, OFTrue /* replace old */); + if (result.bad()) + delete ss; + return result; } - OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedUnsigned(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueLastValueMapped); - OFCondition result = us->putUint16(value); - if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); - if (result.bad()) delete us; - return result; + (void)checkValue; + DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueLastValueMapped); + OFCondition result = us->putUint16(value); + if (result.good()) + result = m_Item->insert(us, OFTrue /* replace old */); + if (result.bad()) + delete us; + return result; } - OFCondition FGRealWorldValueMapping::RWVMItem::setDoubleFloatRealWorldValueFirstValueMapped(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value); + (void)checkValue; + return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value); } - OFCondition FGRealWorldValueMapping::RWVMItem::setDoubleFloatRealWorldValueLastValueMapped(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueLastValueMapped, value); + (void)checkValue; + return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueLastValueMapped, value); } - -OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueIntercept(const Float64 value, - const OFBool checkValue) +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueIntercept(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_RealWorldValueIntercept, value); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_RealWorldValueIntercept, value); } - -OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueSlope(const Float64 value, - const OFBool checkValue) +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueSlope(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_RealWorldValueSlope, value); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_RealWorldValueSlope, value); } - -OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLUTData(const OFVector< Float64 >& value, +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLUTData(const OFVector& value, const OFBool checkValue) { - (void)checkValue; - DcmElement *elem = NULL; - OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); - if (result.good()) - { - size_t count = value.size(); - for (size_t n = 0; n < count; n++) + (void)checkValue; + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); + if (result.good()) { - if (result.good()) result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + size_t count = value.size(); + for (size_t n = 0; n < count; n++) + { + if (result.good()) + result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + } } - } - return result; + return result; } - -OFCondition FGRealWorldValueMapping::RWVMItem::setLUTExplanation(const OFString& value, - const OFBool checkValue) +OFCondition FGRealWorldValueMapping::RWVMItem::setLUTExplanation(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LUTExplanation, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LUTExplanation, value); + return result; } - -OFCondition FGRealWorldValueMapping::RWVMItem::setLUTLabel(const OFString& value, - const OFBool checkValue) +OFCondition FGRealWorldValueMapping::RWVMItem::setLUTLabel(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LUTLabel, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LUTLabel, value); + return result; } - OFCondition FGRealWorldValueMapping::RWVMItem::getUSorSS(DcmItem& item, const DcmTagKey& key, const unsigned long pos, Sint32& value) { - DcmElement *elem = NULL; - OFCondition result = item.findAndGetElement(key, elem); - if (result.good() && elem) - { - DcmEVR evr = elem->getVR(); - if (evr == EVR_US) + DcmElement* elem = NULL; + OFCondition result = item.findAndGetElement(key, elem); + if (result.good() && elem) { - Uint16 num; - result = elem->getUint16(num, pos); - if (result.good()) value = num; + DcmEVR evr = elem->getVR(); + if (evr == EVR_US) + { + Uint16 num; + result = elem->getUint16(num, pos); + if (result.good()) + value = num; + } + else if (evr == EVR_SS) + { + Sint16 num; + result = elem->getSint16(num, pos); + if (result.good()) + value = num; + } + else + { + DCMFG_ERROR("Illegal VR " << DcmVR(evr).getVRName() << " for tag " << DcmTag(key).getTagName()); + result = EC_InvalidVR; + } } - else if (evr == EVR_SS) - { - Sint16 num; - result = elem->getSint16(num, pos); - if (result.good()) value = num; - } - else - { - DCMFG_ERROR("Illegal VR " << DcmVR(evr).getVRName() << " for tag " << DcmTag(key).getTagName()); - result = EC_InvalidVR; - } - } - return result; + return result; } diff --git a/dcmfg/libsrc/fgseg.cc b/dcmfg/libsrc/fgseg.cc index 99850107..71b44edd 100644 --- a/dcmfg/libsrc/fgseg.cc +++ b/dcmfg/libsrc/fgseg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,121 +20,113 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgseg.h" + #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgseg.h" #include "dcmtk/dcmiod/iodutil.h" // for static element helpers - -FGSegmentation::FGSegmentation() : - FGBase(DcmFGTypes::EFG_SEGMENTATION), - m_ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) +FGSegmentation::FGSegmentation() + : FGBase(DcmFGTypes::EFG_SEGMENTATION) + , m_ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) { } - FGSegmentation::~FGSegmentation() { - clearData(); + clearData(); } FGBase* FGSegmentation::clone() const { - FGSegmentation* copy = new FGSegmentation(); - if (copy) - { - copy->m_ReferencedSegmentNumber = this->m_ReferencedSegmentNumber; - } - return copy; + FGSegmentation* copy = new FGSegmentation(); + if (copy) + { + copy->m_ReferencedSegmentNumber = this->m_ReferencedSegmentNumber; + } + return copy; } - - void FGSegmentation::clearData() { - m_ReferencedSegmentNumber.clear(); + m_ReferencedSegmentNumber.clear(); } - OFCondition FGSegmentation::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - -OFCondition FGSegmentation::getReferencedSegmentNumber(Uint16& value, - const unsigned long pos) +OFCondition FGSegmentation::getReferencedSegmentNumber(Uint16& value, const unsigned long pos) { - return m_ReferencedSegmentNumber.getUint16(value, pos); + return m_ReferencedSegmentNumber.getUint16(value, pos); } - OFCondition FGSegmentation::setReferencedSegmentNumber(const Uint16& segmentNumber) { - return m_ReferencedSegmentNumber.putUint16(segmentNumber); + return m_ReferencedSegmentNumber.putUint16(segmentNumber); } - OFCondition FGSegmentation::write(DcmItem& item) { - OFCondition result = EC_Normal; - - /* Clear old data */ - item.findAndDeleteElement(DCM_SegmentIdentificationSequence); - - /* write and get Segment Identification Sequence with one item */ - DcmItem *newItem = NULL; - result = item.findOrCreateSequenceItem(DCM_SegmentIdentificationSequence, newItem, 0); - if ( result.bad() ) - { - DCMFG_ERROR("Could not create Segment Identification Sequence with one item (internal error): " << result.text()); - return FG_EC_CouldNotWriteFG; - } - DcmIODUtil::copyElementToDataset(result, *newItem, m_ReferencedSegmentNumber, "1-n", "1", "SegmentationMacro"); - - /* Return result */ - return result; -} + OFCondition result = EC_Normal; + + /* Clear old data */ + item.findAndDeleteElement(DCM_SegmentIdentificationSequence); + + /* write and get Segment Identification Sequence with one item */ + DcmItem* newItem = NULL; + result = item.findOrCreateSequenceItem(DCM_SegmentIdentificationSequence, newItem, 0); + if (result.bad()) + { + DCMFG_ERROR( + "Could not create Segment Identification Sequence with one item (internal error): " << result.text()); + return FG_EC_CouldNotWriteFG; + } + DcmIODUtil::copyElementToDataset(result, *newItem, m_ReferencedSegmentNumber, "1-n", "1", "SegmentationMacro"); + /* Return result */ + return result; +} OFCondition FGSegmentation::read(DcmItem& item) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - /* re-initialize object */ - clearData(); + /* re-initialize object */ + clearData(); - DcmSequenceOfItems *segmentIdentificationSequence = NULL; - result = item.findAndGetSequence(DCM_SegmentIdentificationSequence, segmentIdentificationSequence); + DcmSequenceOfItems* segmentIdentificationSequence = NULL; + result = item.findAndGetSequence(DCM_SegmentIdentificationSequence, segmentIdentificationSequence); - if ( result.good() ) - { - /* Referenced Segment Number */ - // check whether structure is ok (single item in sequence) and report problems - DcmItem *idItem= NULL; - DcmIODUtil::getAndCheckSingleItem(*segmentIdentificationSequence, idItem, DCM_SegmentIdentificationSequence); - if (idItem) + if (result.good()) { - // so far we ignore the result when reading (but report problems to the logger) - DcmIODUtil::getAndCheckElementFromDataset(*idItem, m_ReferencedSegmentNumber, "1-n" /* vm */, "1" /* type */, "SegmentationMacro"); + /* Referenced Segment Number */ + // check whether structure is ok (single item in sequence) and report problems + DcmItem* idItem = NULL; + DcmIODUtil::getAndCheckSingleItem(*segmentIdentificationSequence, idItem, DCM_SegmentIdentificationSequence); + if (idItem) + { + // so far we ignore the result when reading (but report problems to the logger) + DcmIODUtil::getAndCheckElementFromDataset( + *idItem, m_ReferencedSegmentNumber, "1-n" /* vm */, "1" /* type */, "SegmentationMacro"); + } } - } - return result; + return result; } - int FGSegmentation::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result == 0) - { - const FGSegmentation* myRhs = OFstatic_cast(const FGSegmentation*, &rhs); - if (!myRhs) - return -1; - - // Compare all elements - result = m_ReferencedSegmentNumber.compare(myRhs->m_ReferencedSegmentNumber); - } - - return result; + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGSegmentation* myRhs = OFstatic_cast(const FGSegmentation*, &rhs); + if (!myRhs) + return -1; + + // Compare all elements + result = m_ReferencedSegmentNumber.compare(myRhs->m_ReferencedSegmentNumber); + } + + return result; } diff --git a/dcmfg/libsrc/fgtemporalposition.cc b/dcmfg/libsrc/fgtemporalposition.cc new file mode 100644 index 00000000..27a4a75a --- /dev/null +++ b/dcmfg/libsrc/fgtemporalposition.cc @@ -0,0 +1,114 @@ +/* + * + * Copyright (C) 2019, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Temporal Position + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmfg/fgtemporalposition.h" +#include "dcmtk/dcmiod/iodutil.h" + +FGTemporalPosition::FGTemporalPosition() + : FGBase(DcmFGTypes::EFG_TEMPORALPOSITION) + , m_TemporalPositionTimeOffset(DCM_TemporalPositionTimeOffset) +{ +} + +FGTemporalPosition::~FGTemporalPosition() +{ +} + +void FGTemporalPosition::clearData() +{ + m_TemporalPositionTimeOffset.clear(); +} + +OFCondition FGTemporalPosition::check() const +{ + return EC_Normal; +} + +FGBase* FGTemporalPosition::clone() const +{ + if (FGTemporalPosition* copy = new FGTemporalPosition) + { + copy->m_TemporalPositionTimeOffset = m_TemporalPositionTimeOffset; + return copy; + } + return OFnullptr; +} + +OFCondition FGTemporalPosition::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem; + OFCondition result; + + seqItem = OFnullptr; + result = getItemFromFGSequence(item, DCM_TemporalPositionSequence, 0, seqItem); + if (result.bad()) + return result; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TemporalPositionTimeOffset, "1", "1", "Temporal Position"); + + return EC_Normal; +} + +OFCondition FGTemporalPosition::write(DcmItem& item) +{ + DcmItem* seqItem; + OFCondition result = check(); + if (result.bad()) + return result; + + seqItem = OFnullptr; + result = createNewFGSequence(item, DCM_TemporalPositionSequence, 0, seqItem); + if (result.bad()) + return result; + DcmIODUtil::copyElementToDataset(result, *seqItem, m_TemporalPositionTimeOffset, "1", "1", "Temporal Position"); + + return result; +} + +int FGTemporalPosition::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGTemporalPosition* myRhs = OFstatic_cast(const FGTemporalPosition*, &rhs); + + // Compare all elements + result = m_TemporalPositionTimeOffset.compare(myRhs->m_TemporalPositionTimeOffset); + } + + return result; +} + +OFCondition FGTemporalPosition::getTemporalPositionTimeOffset(Float64& value, const unsigned long pos) const +{ + return DcmIODUtil::getFloat64ValueFromElement(m_TemporalPositionTimeOffset, value, pos); +} + +OFCondition FGTemporalPosition::setTemporalPositionTimeOffset(const Float64& value, const OFBool checkValue) +{ + // Maybe add checks later. + (void)checkValue; + return m_TemporalPositionTimeOffset.putFloat64(value); +} diff --git a/dcmfg/libsrc/fgtypes.cc b/dcmfg/libsrc/fgtypes.cc index 9fd72311..0ff72e4f 100644 --- a/dcmfg/libsrc/fgtypes.cc +++ b/dcmfg/libsrc/fgtypes.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,10 +20,11 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/fgtypes.h" + #include "dcmtk/dcmdata/dcerror.h" -#include "dcmtk/dcmfg/fgdefine.h" #include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmfg/fgtypes.h" #include "dcmtk/dcmiod/iodcommn.h" OFLogger DCM_dcmfgLogger = OFLog::getLogger("dcmtk.dcmfg"); @@ -32,156 +33,274 @@ OFLogger DCM_dcmfgLogger = OFLog::getLogger("dcmtk.dcmfg"); * constant definitions *---------------------------------*/ -// conditions -makeOFConditionConst(FG_EC_DoubledFG, OFM_dcmfg, 1, OF_error, "Doubled Functional Group"); -makeOFConditionConst(FG_EC_NoSuchGroup, OFM_dcmfg, 2, OF_error, "No such Functional Group"); -makeOFConditionConst(FG_EC_NotEnoughItems, OFM_dcmfg, 3, OF_error, "Not enough Items in Functional Group"); -makeOFConditionConst(FG_EC_TooManyItems, OFM_dcmfg, 4, OF_error, "Too many Items in Functional Group"); -makeOFConditionConst(FG_EC_InvalidData, OFM_dcmfg, 5, OF_error, "Invalid data in Functional Group"); -makeOFConditionConst(FG_EC_CouldNotWriteFG, OFM_dcmfg, 6, OF_error, "Could not write Functional Group"); -makeOFConditionConst(FG_EC_CouldNotInsertFG, OFM_dcmfg, 7, OF_error, "Could not insert Functional Group"); -makeOFConditionConst(FG_EC_NoSharedFG, OFM_dcmfg, 8, OF_error, "No shared Functional Groups found"); -makeOFConditionConst(FG_EC_NoPerFrameFG, OFM_dcmfg, 9, OF_error, "No Per-Frame Functional Groups found"); -makeOFConditionConst(FG_EC_CouldNotCreateFG, OFM_dcmfg, 10, OF_error, "Could not create Functional Group"); +// Error Conditions +makeOFConditionConst(FG_EC_DoubledFG, OFM_dcmfg, 1, OF_error, "Doubled Functional Group"); +makeOFConditionConst(FG_EC_NoSuchGroup, OFM_dcmfg, 2, OF_error, "No such Functional Group"); +makeOFConditionConst(FG_EC_NotEnoughItems, OFM_dcmfg, 3, OF_error, "Not enough Items in Functional Group"); +makeOFConditionConst(FG_EC_TooManyItems, OFM_dcmfg, 4, OF_error, "Too many Items in Functional Group"); +makeOFConditionConst(FG_EC_InvalidData, OFM_dcmfg, 5, OF_error, "Invalid data in Functional Group"); +makeOFConditionConst(FG_EC_CouldNotWriteFG, OFM_dcmfg, 6, OF_error, "Could not write Functional Group"); +makeOFConditionConst(FG_EC_CouldNotInsertFG, OFM_dcmfg, 7, OF_error, "Could not insert Functional Group"); +makeOFConditionConst(FG_EC_NoSharedFG, OFM_dcmfg, 8, OF_error, "No shared Functional Groups found"); +makeOFConditionConst(FG_EC_NoPerFrameFG, OFM_dcmfg, 9, OF_error, "No Per-Frame Functional Groups found"); +makeOFConditionConst(FG_EC_CouldNotCreateFG, OFM_dcmfg, 10, OF_error, "Could not create Functional Group"); makeOFConditionConst(FG_EC_CouldNotReadSourceImage, OFM_dcmfg, 11, OF_error, "Could not read source image"); -makeOFConditionConst(FG_EC_CouldNotAddFG, OFM_dcmfg, 12, OF_error, "Could add Functional Group"); -makeOFConditionConst(FG_EC_NotEnoughFrames, OFM_dcmfg, 13, OF_error, "Not enough frames"); -makeOFConditionConst(FG_EC_NoStacksFound, OFM_dcmfg, 14, OF_error, "No stacks found"); - +makeOFConditionConst(FG_EC_CouldNotAddFG, OFM_dcmfg, 12, OF_error, "Could add Functional Group"); +makeOFConditionConst(FG_EC_NotEnoughFrames, OFM_dcmfg, 13, OF_error, "Not enough frames"); +makeOFConditionConst(FG_EC_NoStacksFound, OFM_dcmfg, 14, OF_error, "No stacks found"); +makeOFConditionConst(FG_EC_SOPClassForbidsConcatenations, OFM_dcmfg, 15, OF_error, "SOP Class forbids Concatenations"); +makeOFConditionConst(FG_EC_PixelDataMissing, OFM_dcmfg, 16, OF_error, "Pixel Data is missing"); +makeOFConditionConst(FG_EC_PixelDataDimensionsInvalid, OFM_dcmfg, 17, OF_error, "Pixel Data dimensions invalid"); +makeOFConditionConst(FG_EC_PixelDataTooLarge, OFM_dcmfg, 18, OF_error, "Pixel Data too large"); +makeOFConditionConst(FG_EC_InconsistentConcatenationData, OFM_dcmfg, 19, OF_error, "Inconsistent Concatenation Data"); +makeOFConditionConst(FG_EC_ConcatenationComplete, OFM_dcmfg, 20, OF_error, "Concatenation Complete - no more data"); +makeOFConditionConst(FG_EC_UnsupportedPixelDataLayout, OFM_dcmfg, 21, OF_error, "Unsupported pixel data layout"); OFString DcmFGTypes::FGType2OFString(const DcmFGTypes::E_FGType fgType) { - switch (fgType) - { - /// Undefined functional group - case EFG_UNDEFINED: return "Undefined Functional Group Macro"; break; - /// Unknown functional group - case EFG_UNKNOWN: return "Unknown Functional Group Macro"; break; - /// Pixel Measures - case EFG_PIXELMEASURES: return "Pixel Measures Functional Group Macro"; break; - /// Frame Content - case EFG_FRAMECONTENT: return "Frame Content Functional Group Macro"; break; - /// Plane Position (Patient) - case EFG_PLANEPOSPATIENT: return "Plane Position (Patient) Functional Group Macro"; break; - /// Plane Orientation (Patient) - case EFG_PLANEORIENTPATIENT: return "Plane Orientation (Patient) Functional Group Macro"; break; - /// Derivation Image - case EFG_DERIVATIONIMAGE: return "Derivation Image Functional Group Macro"; break; - /// Cardiac Synchronization - case EFG_CARDIACSYNC: return "Cardiac Synchronization Functional Group Macro"; break; - /// Frame Anatomy - case EFG_FRAMEANATOMY: return "Frame Anatomy Functional Group Macro"; break; - /// Pixel Value Transformation or Identity Pixel Value Transformation - case EFG_PIXELVALUETRANSMETA: return "Pixel Value Transformation / Identity Pixel Value Transformation Functional Group Macro"; break; - /// Frame VOI LUT or Frame VOI LUT with LUT - case EFG_FRAMEVOILUTMETA: return "Frame VOI LUT / Frame VOI LUT with LUT Macro"; break; - /// Real World Value Mapping - case EFG_REALWORLDVALUEMAPPING: return "Real World Value Mapping Functional Group Macro"; break; - /// Contrast/Bolus Usage - case EFG_CONTRASTBOLUSUSAGE: return "Contrast/Bolus Usage Group Macro"; break; - /// Pixel Intensity Relationship LUT - case EFG_PIXELINTENSITYRELLUT: return "Pixel Intensity Relation LUT Functional Group Macro"; break; - /// Frame Pixel Shift - case EFG_FRAMEPIXELSHIFT: return "Frame Pixel Shift Functional Group Macro"; break; - /// Patient Orientation in Frame - case EFG_PATIENTORIENTINFRAME: return "Patient Orientation in Frame Functional Group Macro"; break; - /// Frame Display Shutter - case EFG_FRAMEDISPLAYSHUTTER: return "Frame Display Shutter Functional Group Macro"; break; - /// Respiratory Synchronization - case EFG_RESPIRATORYSYNC: return "Respiratory Synchronization Functional Group Macro"; break; - /// Irradiation Event Identification - case EFG_IRRADIATIONEVENTIDENT: return "Irradiation Event Identification Functional Group Macro"; break; - /// Radiopharmaceutical Usage - case EFG_RADIOPHARAMAUSAGE: return "Radiopharmaceutical Usage Functional Group Macro"; break; - /// Parametric Map Frame Type - case EFG_PARAMETRICMAPFRAMETYPE: return "Parametric Map Frame Type Functional Group Macro"; break; - /// Patient Physiological State - case EFG_PATIENTPHYSIOSTATE: return "Patient Physiological State Functional Group Macro"; break; - /// Plane Position (Volume) - case EFG_PLANEPOSITIONVOLUME: return "Plane Position (Volume) Functional Group Macro"; break; - /// Plane Orientation (Volume) - case EFG_PLANEORIENTVOLUME: return "Plane Orientation (Volume) Functional Group Macro"; break; - /// Temporal Position Macro - case EFG_TEMPORALPOSITION: return "Temporal Position Functional Group Macro"; break; - /// Image Data Type - case EFG_IMAGEDATATYPE: return "Image Data Type Functional Group Macro"; break; - /// Unassigned Shared Converted Attributes Macro - case EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES: return "Unassigned Shared Converted Attributes Macro"; break; - /// Segmentation Macro - case EFG_SEGMENTATION: return "Segmentation Functional Group Macro"; break; - /// US Image Description Functional Group Macro - case EFG_USIMAGEDESCRIPTION: return "US Image Description Functional Group Macro"; break; - } - return "Unknown Functional Group Macro (internal error)"; + switch (fgType) + { + /// Undefined functional group + case EFG_UNDEFINED: + return "Undefined Functional Group Macro"; + break; + /// Unknown functional group + case EFG_UNKNOWN: + return "Unknown Functional Group Macro"; + break; + /// Pixel Measures + case EFG_PIXELMEASURES: + return "Pixel Measures Functional Group Macro"; + break; + /// Frame Content + case EFG_FRAMECONTENT: + return "Frame Content Functional Group Macro"; + break; + /// CT Acquisition Details + case EFG_CTACQUISITIONDETAILS: + return "CT Acquisition Details Functional Group Macro"; + break; + /// CT Acquisition Type + case EFG_CTACQUISITIONTYPE: + return "CT Acquisition Type Functional Group Macro"; + break; + /// CT Additional X-Ray Source + case EFG_CTADDITIONALXRAYSOURCE: + return "CT Additional X-Ray Source"; + break; + /// CT Exposure + case EFG_CTEXPOSURE: + return "CT Exposure Functional Group Macro"; + break; + case EFG_CTGEOMETRY: + return "CT Geometry Functional Group Macro"; + /// CT Image Frame Type + case EFG_CTIMAGEFRAMETYPE: + return "CT Image Frame Type Functional Group Macro"; + break; + /// CT Position + case EFG_CTPOSITION: + return "CT Position Functional Group Macro"; + break; + /// CT Reconstruction + case EFG_CTRECONSTRUCTION: + return "CT Reconstruction Functional Group Macro"; + break; + /// CT Table Dynamics + case EFG_CTTABLEDYNAMICS: + return "CT Table Dynamics Functional Group Macro"; + break; + /// CT X-Ray Details + case EFG_CTXRAYDETAILS: + return "CT X-Ray Details Functional Group Macro"; + break; + /// Plane Position (Patient) + case EFG_PLANEPOSPATIENT: + return "Plane Position (Patient) Functional Group Macro"; + break; + /// Plane Orientation (Patient) + case EFG_PLANEORIENTPATIENT: + return "Plane Orientation (Patient) Functional Group Macro"; + break; + /// Derivation Image + case EFG_DERIVATIONIMAGE: + return "Derivation Image Functional Group Macro"; + break; + /// Cardiac Synchronization + case EFG_CARDIACSYNC: + return "Cardiac Synchronization Functional Group Macro"; + break; + /// Frame Anatomy + case EFG_FRAMEANATOMY: + return "Frame Anatomy Functional Group Macro"; + break; + /// Pixel Value Transformation or Identity Pixel Value Transformation + case EFG_PIXELVALUETRANSMETA: + return "[CT|Identity] Pixel Value Transformation Functional Group Macro"; + break; + /// Frame VOI LUT or Frame VOI LUT with LUT + case EFG_FRAMEVOILUTMETA: + return "Frame VOI LUT / Frame VOI LUT with LUT Macro"; + break; + /// Real World Value Mapping + case EFG_REALWORLDVALUEMAPPING: + return "Real World Value Mapping Functional Group Macro"; + break; + /// Contrast/Bolus Usage + case EFG_CONTRASTBOLUSUSAGE: + return "Contrast/Bolus Usage Group Macro"; + break; + /// Pixel Intensity Relationship LUT + case EFG_PIXELINTENSITYRELLUT: + return "Pixel Intensity Relation LUT Functional Group Macro"; + break; + /// Frame Pixel Shift + case EFG_FRAMEPIXELSHIFT: + return "Frame Pixel Shift Functional Group Macro"; + break; + /// Patient Orientation in Frame + case EFG_PATIENTORIENTINFRAME: + return "Patient Orientation in Frame Functional Group Macro"; + break; + /// Frame Display Shutter + case EFG_FRAMEDISPLAYSHUTTER: + return "Frame Display Shutter Functional Group Macro"; + break; + /// Respiratory Synchronization + case EFG_RESPIRATORYSYNC: + return "Respiratory Synchronization Functional Group Macro"; + break; + /// Irradiation Event Identification + case EFG_IRRADIATIONEVENTIDENT: + return "Irradiation Event Identification Functional Group Macro"; + break; + /// Radiopharmaceutical Usage + case EFG_RADIOPHARAMAUSAGE: + return "Radiopharmaceutical Usage Functional Group Macro"; + break; + /// Parametric Map Frame Type + case EFG_PARAMETRICMAPFRAMETYPE: + return "Parametric Map Frame Type Functional Group Macro"; + break; + /// Patient Physiological State + case EFG_PATIENTPHYSIOSTATE: + return "Patient Physiological State Functional Group Macro"; + break; + /// Plane Position (Volume) + case EFG_PLANEPOSITIONVOLUME: + return "Plane Position (Volume) Functional Group Macro"; + break; + /// Plane Orientation (Volume) + case EFG_PLANEORIENTVOLUME: + return "Plane Orientation (Volume) Functional Group Macro"; + break; + /// Temporal Position Macro + case EFG_TEMPORALPOSITION: + return "Temporal Position Functional Group Macro"; + break; + /// Image Data Type + case EFG_IMAGEDATATYPE: + return "Image Data Type Functional Group Macro"; + break; + /// Unassigned Shared Converted Attributes Macro + case EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES: + return "Unassigned Shared Converted Attributes Macro"; + break; + /// Segmentation Macro + case EFG_SEGMENTATION: + return "Segmentation Functional Group Macro"; + break; + /// US Image Description Functional Group Macro + case EFG_USIMAGEDESCRIPTION: + return "US Image Description Functional Group Macro"; + break; + } + return "Unknown Functional Group Macro (internal error)"; } - DcmFGTypes::E_FGType DcmFGTypes::tagKey2FGType(const DcmTagKey& key) { - // Note: Use neat value to enum trick from Alexandrescu in order to have switch statement instead? - if (key == DCM_PixelMeasuresSequence) - return EFG_PIXELMEASURES; - else if (key == DCM_FrameContentSequence) - return EFG_FRAMECONTENT; - else if (key == DCM_PlanePositionSequence) - return EFG_PLANEPOSPATIENT; - else if (key == DCM_PlaneOrientationSequence) - return EFG_PLANEORIENTPATIENT; - else if (key == DCM_DerivationImageSequence) - return EFG_DERIVATIONIMAGE; - else if (key == DCM_CardiacSynchronizationSequence) - return EFG_CARDIACSYNC; - else if (key == DCM_FrameAnatomySequence) - return EFG_FRAMEANATOMY; - else if (key == DCM_PixelValueTransformationSequence) - return EFG_PIXELVALUETRANSMETA; - else if (key == DCM_FrameVOILUTSequence) - return EFG_FRAMEVOILUTMETA; - else if (key == DCM_RealWorldValueMappingSequence) - return EFG_REALWORLDVALUEMAPPING; - else if (key == DCM_ContrastBolusUsageSequence) - return EFG_CONTRASTBOLUSUSAGE; - else if (key == DCM_PixelIntensityRelationshipLUTSequence) - return EFG_PIXELINTENSITYRELLUT; - else if (key == DCM_FramePixelShiftSequence) - return EFG_FRAMEPIXELSHIFT; - else if (key == DCM_PatientOrientationInFrameSequence) - return EFG_PATIENTORIENTINFRAME; - else if (key == DCM_FrameDisplayShutterSequence) - return EFG_FRAMEDISPLAYSHUTTER; - else if (key == DCM_RespiratorySynchronizationSequence) - return EFG_RESPIRATORYSYNC; - else if (key == DCM_IrradiationEventIdentificationSequence) - return EFG_IRRADIATIONEVENTIDENT; - else if (key == DCM_RadiopharmaceuticalUsageSequence) - return EFG_RADIOPHARAMAUSAGE; - else if (key == DCM_PatientPhysiologicalStateSequence) - return EFG_PATIENTPHYSIOSTATE; - else if (key == DCM_ParametricMapFrameTypeSequence) - return EFG_PARAMETRICMAPFRAMETYPE; - else if (key == DCM_PlanePositionVolumeSequence) - return EFG_PLANEPOSITIONVOLUME; - else if (key == DCM_PlaneOrientationVolumeSequence) - return EFG_PLANEORIENTVOLUME; - else if (key == DCM_TemporalPositionSequence) - return EFG_TEMPORALPOSITION; - else if (key == DCM_ImageDataTypeSequence) - return EFG_IMAGEDATATYPE; - else if (key == DCM_UnassignedSharedConvertedAttributesSequence) - return EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES; - else if (key == DCM_SegmentIdentificationSequence) - return EFG_SEGMENTATION; - else if (key == DCM_USImageDescriptionSequence) - return EFG_USIMAGEDESCRIPTION; - else - return EFG_UNKNOWN; + // Note: Use neat value to enum trick from Alexandrescu in order to have switch statement instead? + if (key == DCM_PixelMeasuresSequence) + return EFG_PIXELMEASURES; + else if (key == DCM_FrameContentSequence) + return EFG_FRAMECONTENT; + else if (key == DCM_CTAcquisitionDetailsSequence) + return EFG_CTACQUISITIONDETAILS; + else if (key == DCM_CTAdditionalXRaySourceSequence) + return EFG_CTADDITIONALXRAYSOURCE; + else if (key == DCM_CTAcquisitionTypeSequence) + return EFG_CTACQUISITIONTYPE; + else if (key == DCM_CTExposureSequence) + return EFG_CTEXPOSURE; + else if (key == DCM_CTGeometrySequence) + return EFG_CTGEOMETRY; + else if (key == DCM_CTImageFrameTypeSequence) + return EFG_CTIMAGEFRAMETYPE; + else if (key == DCM_CTPositionSequence) + return EFG_CTPOSITION; + else if (key == DCM_CTReconstructionSequence) + return EFG_CTRECONSTRUCTION; + else if (key == DCM_CTTableDynamicsSequence) + return EFG_CTTABLEDYNAMICS; + else if (key == DCM_CTXRayDetailsSequence) + return EFG_CTXRAYDETAILS; + else if (key == DCM_PlanePositionSequence) + return EFG_PLANEPOSPATIENT; + else if (key == DCM_PlaneOrientationSequence) + return EFG_PLANEORIENTPATIENT; + else if (key == DCM_DerivationImageSequence) + return EFG_DERIVATIONIMAGE; + else if (key == DCM_CardiacSynchronizationSequence) + return EFG_CARDIACSYNC; + else if (key == DCM_FrameAnatomySequence) + return EFG_FRAMEANATOMY; + else if (key == DCM_PixelValueTransformationSequence) + return EFG_PIXELVALUETRANSMETA; + else if (key == DCM_FrameVOILUTSequence) + return EFG_FRAMEVOILUTMETA; + else if (key == DCM_RealWorldValueMappingSequence) + return EFG_REALWORLDVALUEMAPPING; + else if (key == DCM_ContrastBolusUsageSequence) + return EFG_CONTRASTBOLUSUSAGE; + else if (key == DCM_PixelIntensityRelationshipLUTSequence) + return EFG_PIXELINTENSITYRELLUT; + else if (key == DCM_FramePixelShiftSequence) + return EFG_FRAMEPIXELSHIFT; + else if (key == DCM_PatientOrientationInFrameSequence) + return EFG_PATIENTORIENTINFRAME; + else if (key == DCM_FrameDisplayShutterSequence) + return EFG_FRAMEDISPLAYSHUTTER; + else if (key == DCM_RespiratorySynchronizationSequence) + return EFG_RESPIRATORYSYNC; + else if (key == DCM_IrradiationEventIdentificationSequence) + return EFG_IRRADIATIONEVENTIDENT; + else if (key == DCM_RadiopharmaceuticalUsageSequence) + return EFG_RADIOPHARAMAUSAGE; + else if (key == DCM_PatientPhysiologicalStateSequence) + return EFG_PATIENTPHYSIOSTATE; + else if (key == DCM_ParametricMapFrameTypeSequence) + return EFG_PARAMETRICMAPFRAMETYPE; + else if (key == DCM_PlanePositionVolumeSequence) + return EFG_PLANEPOSITIONVOLUME; + else if (key == DCM_PlaneOrientationVolumeSequence) + return EFG_PLANEORIENTVOLUME; + else if (key == DCM_TemporalPositionSequence) + return EFG_TEMPORALPOSITION; + else if (key == DCM_ImageDataTypeSequence) + return EFG_IMAGEDATATYPE; + else if (key == DCM_UnassignedSharedConvertedAttributesSequence) + return EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES; + else if (key == DCM_SegmentIdentificationSequence) + return EFG_SEGMENTATION; + else if (key == DCM_USImageDescriptionSequence) + return EFG_USIMAGEDESCRIPTION; + else + return EFG_UNKNOWN; } - OFString DcmFGTypes::tagKey2FGString(const DcmTagKey& key) { - E_FGType fgtype = tagKey2FGType(key); - return FGType2OFString(fgtype); + E_FGType fgtype = tagKey2FGType(key); + return FGType2OFString(fgtype); } - - diff --git a/dcmfg/libsrc/fgusimagedescription.cc b/dcmfg/libsrc/fgusimagedescription.cc index 53a3339c..b9d40931 100644 --- a/dcmfg/libsrc/fgusimagedescription.cc +++ b/dcmfg/libsrc/fgusimagedescription.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,192 +20,181 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmiod/iodutil.h" -#include "dcmtk/dcmiod/iodtypes.h" #include "dcmtk/dcmfg/fgusimagedescription.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmiod/iodutil.h" // Constructor -FGUSImageDescription::FGUSImageDescription() : - FGBase(DcmFGTypes::EFG_USIMAGEDESCRIPTION), - m_FrameType(DCM_FrameType), - m_VolumetricProperties(DCM_VolumetricProperties), - m_VolumeBasedCalculationTechnique(DCM_VolumeBasedCalculationTechnique) +FGUSImageDescription::FGUSImageDescription() + : FGBase(DcmFGTypes::EFG_USIMAGEDESCRIPTION) + , m_FrameType(DCM_FrameType) + , m_VolumetricProperties(DCM_VolumetricProperties) + , m_VolumeBasedCalculationTechnique(DCM_VolumeBasedCalculationTechnique) { } - FGUSImageDescription::~FGUSImageDescription() { - // nothing to do + // nothing to do } - FGBase* FGUSImageDescription::clone() const { - FGUSImageDescription* copy = new FGUSImageDescription(); - if (copy) - { - copy->m_FrameType = this->m_FrameType; - copy->m_VolumetricProperties = this->m_VolumetricProperties; - copy->m_VolumeBasedCalculationTechnique = this->m_VolumeBasedCalculationTechnique; - } - return copy; + FGUSImageDescription* copy = new FGUSImageDescription(); + if (copy) + { + copy->m_FrameType = this->m_FrameType; + copy->m_VolumetricProperties = this->m_VolumetricProperties; + copy->m_VolumeBasedCalculationTechnique = this->m_VolumeBasedCalculationTechnique; + } + return copy; } - void FGUSImageDescription::clearData() { - m_FrameType.clear(); - m_VolumetricProperties.clear(); - m_VolumeBasedCalculationTechnique.clear(); + m_FrameType.clear(); + m_VolumetricProperties.clear(); + m_VolumeBasedCalculationTechnique.clear(); } - OFCondition FGUSImageDescription::check() const { - // Checks in read() and write() are sufficient for now - return EC_Normal; + // Checks in read() and write() are sufficient for now + return EC_Normal; } - // --- get() functionality --- -OFCondition FGUSImageDescription::getFrameType(OFString& value, - const long signed int pos) +OFCondition FGUSImageDescription::getFrameType(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); + return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); } - -OFCondition FGUSImageDescription::getVolumetricProperties(OFString& value, - const long signed int pos) +OFCondition FGUSImageDescription::getVolumetricProperties(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_VolumetricProperties, value, pos); + return DcmIODUtil::getStringValueFromElement(m_VolumetricProperties, value, pos); } - -OFCondition FGUSImageDescription::getVolumeBasedCalculationTechnique(OFString& value, - const long signed int pos) +OFCondition FGUSImageDescription::getVolumeBasedCalculationTechnique(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_VolumeBasedCalculationTechnique, value, pos); + return DcmIODUtil::getStringValueFromElement(m_VolumeBasedCalculationTechnique, value, pos); } - // --- set() functionality --- - OFCondition FGUSImageDescription::setFrameType(const DcmFGTypes::E_FGUSFrameType pixelDataChar, const OFString& imageFlavor, const OFString& derivedPixelContrast, const OFBool checkValue) { - // Build a string of VM 4 with first two values at least set - OFString value; - switch (pixelDataChar) - { - case(DcmFGTypes::EFGFT_ORIGINAL): value = "ORIGINAL\\PRIMARY\\"; break; - case(DcmFGTypes::EFGFT_DERIVED) : value = "DERIVED\\PRIMARY\\"; break; - default: return IOD_EC_InvalidElementValue; - } - value += imageFlavor; - value += "\\"; - value += derivedPixelContrast; - - OFCondition result; - if (checkValue) - { - result = DcmCodeString::checkStringValue(value, "4"); - } - if (result.good()) - { - result = m_FrameType.putOFStringArray(value); - } - return result; + // Build a string of VM 4 with first two values at least set + OFString value; + switch (pixelDataChar) + { + case (DcmFGTypes::EFGFT_ORIGINAL): + value = "ORIGINAL\\PRIMARY\\"; + break; + case (DcmFGTypes::EFGFT_DERIVED): + value = "DERIVED\\PRIMARY\\"; + break; + default: + return IOD_EC_InvalidElementValue; + } + value += imageFlavor; + value += "\\"; + value += derivedPixelContrast; + + OFCondition result; + if (checkValue) + { + result = DcmCodeString::checkStringValue(value, "4"); + } + if (result.good()) + { + result = m_FrameType.putOFStringArray(value); + } + return result; } - -OFCondition FGUSImageDescription::setVolumetricProperties(const OFString& value, - const OFBool checkValue) +OFCondition FGUSImageDescription::setVolumetricProperties(const OFString& value, const OFBool checkValue) { - OFCondition result; - if (checkValue) - { - if ( (value != "VOLUME") && (value != "SAMPLED") && (value != "DISTORTED") && (value != "MIXED") ) - { - result = IOD_EC_InvalidElementValue; - } - else - result = DcmCodeString::checkStringValue(value, "1"); - } - if (result.good()) - { - result = m_VolumetricProperties.putOFStringArray(value); - } - return result; + OFCondition result; + if (checkValue) + { + if ((value != "VOLUME") && (value != "SAMPLED") && (value != "DISTORTED") && (value != "MIXED")) + { + result = IOD_EC_InvalidElementValue; + } + else + result = DcmCodeString::checkStringValue(value, "1"); + } + if (result.good()) + { + result = m_VolumetricProperties.putOFStringArray(value); + } + return result; } - -OFCondition FGUSImageDescription::setVolumeBasedCalculationTechnique(const OFString& value, - const OFBool checkValue) +OFCondition FGUSImageDescription::setVolumeBasedCalculationTechnique(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_VolumeBasedCalculationTechnique.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VolumeBasedCalculationTechnique.putOFStringArray(value); + return result; } - /// Read Frame Content Sequence from given item OFCondition FGUSImageDescription::read(DcmItem& item) { - clearData(); + clearData(); - DcmItem* seqItem = NULL; - OFCondition result = getItemFromFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); + if (result.bad()) + return result; - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); - DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); - return result; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); + return result; } - /// Writes single Frame Content Sequence into given item OFCondition FGUSImageDescription::write(DcmItem& item) { - DcmItem *seqItem = NULL; - OFCondition result = createNewFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); - if (result.bad()) - return result; + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); + if (result.bad()) + return result; - // --- write frame content macro attributes --- - DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); - DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); + DcmIODUtil::copyElementToDataset( + result, *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); - return result; + return result; } - int FGUSImageDescription::compare(const FGBase& rhs) const { - int result = FGBase::compare(rhs); - if (result != 0) - return result; + int result = FGBase::compare(rhs); + if (result != 0) + return result; - const FGUSImageDescription* myRhs = OFstatic_cast(const FGUSImageDescription*, &rhs); - if (!myRhs) - return -1; + const FGUSImageDescription* myRhs = OFstatic_cast(const FGUSImageDescription*, &rhs); + if (!myRhs) + return -1; - // Compare all elements - result = m_FrameType.compare(myRhs->m_FrameType); - if (result == 0) - result = m_VolumetricProperties.compare(myRhs->m_VolumetricProperties); - if (result == 0) - result = m_VolumeBasedCalculationTechnique.compare(myRhs->m_VolumeBasedCalculationTechnique); + // Compare all elements + result = m_FrameType.compare(myRhs->m_FrameType); + if (result == 0) + result = m_VolumetricProperties.compare(myRhs->m_VolumetricProperties); + if (result == 0) + result = m_VolumeBasedCalculationTechnique.compare(myRhs->m_VolumeBasedCalculationTechnique); - return result; + return result; } diff --git a/dcmfg/libsrc/stack.cc b/dcmfg/libsrc/stack.cc index d59f1f4d..1a3913a0 100644 --- a/dcmfg/libsrc/stack.cc +++ b/dcmfg/libsrc/stack.cc @@ -20,88 +20,74 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmfg/stack.h" +#include "dcmtk/dcmfg/stack.h" -FGStack::FGStack(const OFString& stackID, - const OFMap< Uint32, Uint32 > frameNumbers) -: m_StackID(stackID), - m_FrameNumbers(frameNumbers) +FGStack::FGStack(const OFString& stackID, const OFMap frameNumbers) + : m_StackID(stackID) + , m_FrameNumbers(frameNumbers) { - } FGStack::FGStack(const OFString& stackID) -: m_StackID(stackID), - m_FrameNumbers() + : m_StackID(stackID) + , m_FrameNumbers() { - } -OFBool FGStack::addFrame(const Uint32 frameNumber, - const Uint32 inStackPos) +OFBool FGStack::addFrame(const Uint32 frameNumber, const Uint32 inStackPos) { - m_FrameNumbers.insert(OFMake_pair(frameNumber, inStackPos)); - return OFTrue; + m_FrameNumbers.insert(OFMake_pair(frameNumber, inStackPos)); + return OFTrue; } - FGStack::~FGStack() { - } - FGStack::const_iterator FGStack::begin() const { - return m_FrameNumbers.begin(); + return m_FrameNumbers.begin(); } - FGStack::iterator FGStack::begin() { - return m_FrameNumbers.begin(); + return m_FrameNumbers.begin(); } - FGStack::const_iterator FGStack::end() const { - return m_FrameNumbers.end(); + return m_FrameNumbers.end(); } - FGStack::iterator FGStack::end() { - return m_FrameNumbers.end(); + return m_FrameNumbers.end(); } - OFString FGStack::getStackID() const { - return m_StackID; + return m_StackID; } - Uint32 FGStack::getInStackPos(const Uint32 frameNumber) const { - FGStack::const_iterator it = m_FrameNumbers.find(frameNumber); - if (it == m_FrameNumbers.end()) - return 0; - else - return (*it).second; + FGStack::const_iterator it = m_FrameNumbers.find(frameNumber); + if (it == m_FrameNumbers.end()) + return 0; + else + return (*it).second; } - -void FGStack::getFramesAtStackPos(const Uint32 inStackPos, - OFVector& resultFrameNumbers) +void FGStack::getFramesAtStackPos(const Uint32 inStackPos, OFVector& resultFrameNumbers) { - FGStack::iterator it = m_FrameNumbers.begin(); - while (it != m_FrameNumbers.end()) - { - if ((*it).second == inStackPos) + FGStack::iterator it = m_FrameNumbers.begin(); + while (it != m_FrameNumbers.end()) { - resultFrameNumbers.push_back( (*it).second); + if ((*it).second == inStackPos) + { + resultFrameNumbers.push_back((*it).second); + } + it++; } - it++; - } } diff --git a/dcmfg/libsrc/stackinterface.cc b/dcmfg/libsrc/stackinterface.cc index c9e0c32a..54a28575 100644 --- a/dcmfg/libsrc/stackinterface.cc +++ b/dcmfg/libsrc/stackinterface.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,257 +19,250 @@ * */ -#include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmfg/stackinterface.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmfg/fgfracon.h" - +#include "dcmtk/dcmiod/iodutil.h" FGStackInterface::FGStackInterface() -: m_Stacks() + : m_Stacks() { } - FGStackInterface::~FGStackInterface() { - while (m_Stacks.size() != 0) - { - OFMap::iterator it = m_Stacks.begin(); - FGStack *toDelete = (*it).second; - m_Stacks.erase(it); - delete toDelete; - } + while (m_Stacks.size() != 0) + { + OFMap::iterator it = m_Stacks.begin(); + FGStack* toDelete = (*it).second; + m_Stacks.erase(it); + delete toDelete; + } } - void FGStackInterface::clear() { - size_t stackSize = m_Stacks.size(); - OFMap::iterator it; - for (size_t count = 0; count < stackSize; count++) - { - it = m_Stacks.begin(); - m_Stacks.erase(it); - } + size_t stackSize = m_Stacks.size(); + OFMap::iterator it; + for (size_t count = 0; count < stackSize; count++) + { + it = m_Stacks.begin(); + m_Stacks.erase(it); + } } - OFCondition FGStackInterface::read(FGInterface& fgSource) { - clear(); - size_t numFrames = fgSource.getNumberOfFrames(); - for (size_t count = 0; count < numFrames; count++) - { - // Get frame content FG if existing - FGFrameContent* fracon = OFstatic_cast(FGFrameContent*, fgSource.get(OFstatic_cast(Uint32, count), DcmFGTypes::EFG_FRAMECONTENT)); - if (fracon != NULL) + clear(); + size_t numFrames = fgSource.getNumberOfFrames(); + for (size_t count = 0; count < numFrames; count++) { - OFString stackID; - Uint32 inStackPos; - // Check whether stack ID is actually present and get value - if ( (fracon->getStackID(stackID).good()) && (fracon->getInStackPositionNumber(inStackPos).good()) ) - { - // Check whether this is a stack ID we do not know yet - OFMap::iterator it = m_Stacks.begin(); - while (it != m_Stacks.end()) + // Get frame content FG if existing + FGFrameContent* fracon + = OFstatic_cast(FGFrameContent*, fgSource.get(OFstatic_cast(Uint32, count), DcmFGTypes::EFG_FRAMECONTENT)); + if (fracon != NULL) { - // If this is an old stack, add frame to it - if ( (*it).second->getStackID() == stackID) - { - // Add frame to stack if it is not in yet - if ( (*it).second->getInStackPos(OFstatic_cast(Uint32, count)) == 0) + OFString stackID; + Uint32 inStackPos; + // Check whether stack ID is actually present and get value + if ((fracon->getStackID(stackID).good()) && (fracon->getInStackPositionNumber(inStackPos).good())) { - (*it).second->addFrame(OFstatic_cast(Uint32, count), inStackPos); + // Check whether this is a stack ID we do not know yet + OFMap::iterator it = m_Stacks.begin(); + while (it != m_Stacks.end()) + { + // If this is an old stack, add frame to it + if ((*it).second->getStackID() == stackID) + { + // Add frame to stack if it is not in yet + if ((*it).second->getInStackPos(OFstatic_cast(Uint32, count)) == 0) + { + (*it).second->addFrame(OFstatic_cast(Uint32, count), inStackPos); + } + } + it++; + } + // If this is a new stack, add it to the list + if (it == m_Stacks.end()) + { + FGStack* stack = new FGStack(stackID); + if (stack == NULL) + { + return EC_MemoryExhausted; + } + stack->addFrame(OFstatic_cast(Uint32, count), inStackPos); + if (!m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second) + { + delete stack; + DCMFG_ERROR("Could not add stack to internal list (internal error, ignored)"); + } + } + } + else + { + DCMFG_WARN("Reading stacks but Frame " << count << " does not provide Stack ID or In-Stack Position"); } - } - it++; } - // If this is a new stack, add it to the list - if (it == m_Stacks.end()) + else { - FGStack *stack = new FGStack(stackID); - if (stack == NULL) - { - return EC_MemoryExhausted; - } - stack->addFrame(OFstatic_cast(Uint32, count), inStackPos); - if ( !m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second ) - { - delete stack; - DCMFG_ERROR("Could not add stack to internal list (internal error, ignored)"); - } + DCMFG_WARN("Reading stacks but Frame " << count << " does not provide a Frame Content functional group"); } - } - else - { - DCMFG_WARN("Reading stacks but Frame " << count << " does not provide Stack ID or In-Stack Position"); - } } - else + + if (m_Stacks.size() == 0) { - DCMFG_WARN("Reading stacks but Frame " << count << " does not provide a Frame Content functional group"); + return FG_EC_NoStacksFound; } - } - - if (m_Stacks.size() == 0) - { - return FG_EC_NoStacksFound; - } - return EC_Normal; + return EC_Normal; } - OFCondition FGStackInterface::write(FGInterface& fgDestination) { - size_t numFrames = fgDestination.getNumberOfFrames(); - if (numFrames == 0) - { - return FG_EC_NotEnoughFrames; - } + size_t numFrames = fgDestination.getNumberOfFrames(); + if (numFrames == 0) + { + return FG_EC_NotEnoughFrames; + } - // Check whether maximum in-stack position does not exceed number of frames in image - if (!checkConsistency(&fgDestination)) - { - return FG_EC_InvalidData; - } + // Check whether maximum in-stack position does not exceed number of frames in image + if (!checkConsistency(&fgDestination)) + { + return FG_EC_InvalidData; + } - // Walk through stacks, and for each, add/overwrite stack information to - // the respective Frame Content functional groups - OFCondition result; - OFMap::iterator stack = m_Stacks.begin(); - while (result.good() && (stack != m_Stacks.end()) ) - { - OFString stackID = (*stack).second->getStackID(); - // Walk over all referenced frames and add Stack information - OFMap::const_iterator stackEntry = (*stack).second->begin(); - while (stackEntry != (*stack).second->end()) + // Walk through stacks, and for each, add/overwrite stack information to + // the respective Frame Content functional groups + OFCondition result; + OFMap::iterator stack = m_Stacks.begin(); + while (result.good() && (stack != m_Stacks.end())) { - Uint32 frameNo = (*stackEntry).first; - Uint32 inStackPos = (*stackEntry).second; - FGFrameContent* fg = ensureFrameContentFG(frameNo, fgDestination); - // Create functional group if not already existing - if (fg == NULL) - { - result = FG_EC_CouldNotAddFG; - } - if (result.good()) result = fg->setStackID(stackID); - if (result.good()) result = fg->setInStackPositionNumber(inStackPos+1 /* vector counts from 0, position in DICOM starts with 1 */); - if (result.bad()) - { - DCMFG_ERROR("Could not create or add stack with ID " << stackID << " to frame " << frameNo << ": " << result.text()); - } - stackEntry++; + OFString stackID = (*stack).second->getStackID(); + // Walk over all referenced frames and add Stack information + OFMap::const_iterator stackEntry = (*stack).second->begin(); + while (stackEntry != (*stack).second->end()) + { + Uint32 frameNo = (*stackEntry).first; + Uint32 inStackPos = (*stackEntry).second; + FGFrameContent* fg = ensureFrameContentFG(frameNo, fgDestination); + // Create functional group if not already existing + if (fg == NULL) + { + result = FG_EC_CouldNotAddFG; + } + if (result.good()) + result = fg->setStackID(stackID); + if (result.good()) + result = fg->setInStackPositionNumber(inStackPos + + 1 /* vector counts from 0, position in DICOM starts with 1 */); + if (result.bad()) + { + DCMFG_ERROR("Could not create or add stack with ID " << stackID << " to frame " << frameNo << ": " + << result.text()); + } + stackEntry++; + } + stack++; } - stack++; - } - return result; + return result; } - -FGFrameContent* FGStackInterface::ensureFrameContentFG(const Uint32 frameNo, - FGInterface& fg) +FGFrameContent* FGStackInterface::ensureFrameContentFG(const Uint32 frameNo, FGInterface& fg) { - FGFrameContent* content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); - if (!content) - { - FGFrameContent newContent; - OFCondition result = fg.addPerFrame(frameNo, newContent); - if (result.bad()) - { - DCMFG_ERROR("Could not add Frame Content FG for frame " << frameNo); - } - else + FGFrameContent* content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); + if (!content) { - content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); + FGFrameContent newContent; + OFCondition result = fg.addPerFrame(frameNo, newContent); + if (result.bad()) + { + DCMFG_ERROR("Could not add Frame Content FG for frame " << frameNo); + } + else + { + content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); + } } - } - return content; + return content; } - OFBool FGStackInterface::addStack(FGStack* stack) { - if (stack == NULL) - return OFFalse; + if (stack == NULL) + return OFFalse; - if (stack->getStackID().empty()) - { - DCMFG_ERROR("Stack ID cannot be empty"); - return OFFalse; - } + if (stack->getStackID().empty()) + { + DCMFG_ERROR("Stack ID cannot be empty"); + return OFFalse; + } - return m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second; + return m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second; } - size_t FGStackInterface::numStacks() const { - return m_Stacks.size(); + return m_Stacks.size(); } - OFBool FGStackInterface::checkConsistency(FGInterface* fgContext) { - size_t errors = 0; - size_t count = 0; - // Run over stacks and check whether each has a Stack ID. - // Also check whether stacks can be valid in the context - // of the given functional groups (e.g. frame range ok) - OFMap::iterator it = m_Stacks.begin(); - while (it != m_Stacks.end()) - { - if ( (*it).second->getStackID().empty()) + size_t errors = 0; + size_t count = 0; + // Run over stacks and check whether each has a Stack ID. + // Also check whether stacks can be valid in the context + // of the given functional groups (e.g. frame range ok) + OFMap::iterator it = m_Stacks.begin(); + while (it != m_Stacks.end()) { - errors++; - DCMFG_ERROR("Stack ID for stack #" << count << " is empty"); - } - if (fgContext) - { - errors += checkContext((*it).second, fgContext); + if ((*it).second->getStackID().empty()) + { + errors++; + DCMFG_ERROR("Stack ID for stack #" << count << " is empty"); + } + if (fgContext) + { + errors += checkContext((*it).second, fgContext); + } + it++; + count++; } - it++; - count++; - } - return (errors == 0); + return (errors == 0); } - -size_t FGStackInterface::checkContext(FGStack* stack, - FGInterface* context) +size_t FGStackInterface::checkContext(FGStack* stack, FGInterface* context) { - // Must be non-empty - if ( !stack || !context) - return 1; - - // Check whether we have any frames - size_t numFrames = context->getNumberOfFrames(); - if (numFrames == 0) - { - DCMFG_ERROR("Cannot have stacks without frames"); - return 1; - } + // Must be non-empty + if (!stack || !context) + return 1; - // Walk over frames in stack and check that frame number and - // in-stack position is in range with the number of available frames - size_t errors = 0; - const OFMap& frames = stack->m_FrameNumbers; - FGStack::const_iterator it = frames.begin(); - for (size_t count = 0; count < numFrames; count++) - { - // Frame number must be in range - if ( (*it).first > numFrames ) + // Check whether we have any frames + size_t numFrames = context->getNumberOfFrames(); + if (numFrames == 0) { - DCMFG_ERROR("Stack references frame #" << (*it).first << " but only #" << numFrames << " frames exist"); - errors++; + DCMFG_ERROR("Cannot have stacks without frames"); + return 1; } - if ( (*it).second> numFrames ) + + // Walk over frames in stack and check that frame number and + // in-stack position is in range with the number of available frames + size_t errors = 0; + const OFMap& frames = stack->m_FrameNumbers; + FGStack::const_iterator it = frames.begin(); + for (size_t count = 0; count < numFrames; count++) { - DCMFG_ERROR("Stack references in-stack position #" << (*it).first << " but only #" << numFrames << " frames exist"); - errors++; + // Frame number must be in range + if ((*it).first > numFrames) + { + DCMFG_ERROR("Stack references frame #" << (*it).first << " but only #" << numFrames << " frames exist"); + errors++; + } + if ((*it).second > numFrames) + { + DCMFG_ERROR("Stack references in-stack position #" << (*it).first << " but only #" << numFrames + << " frames exist"); + errors++; + } } - } - return errors; + return errors; } - diff --git a/dcmfg/tests/CMakeLists.txt b/dcmfg/tests/CMakeLists.txt index 7407bd0b..9c56a8cf 100644 --- a/dcmfg/tests/CMakeLists.txt +++ b/dcmfg/tests/CMakeLists.txt @@ -1,5 +1,16 @@ # declare executables -DCMTK_ADD_EXECUTABLE(dcmfg_tests tests t_deriv_image.cc t_frame_content.cc) +DCMTK_ADD_EXECUTABLE(dcmfg_tests + tests + t_concatenation_creator + t_concatenation_loader + t_ct_acquisition_details + t_ct_acquisition_type + t_ct_image_frame_type + t_ct_position + t_ct_table_dynamics + t_deriv_image + t_frame_content + t_irradiation_event_identification) # make sure executables are linked to the corresponding libraries DCMTK_TARGET_LINK_MODULES(dcmfg_tests dcmfg dcmdata oflog ofstd) diff --git a/dcmfg/tests/Makefile.dep b/dcmfg/tests/Makefile.dep index 8dcc7db6..51a0bbec 100644 --- a/dcmfg/tests/Makefile.dep +++ b/dcmfg/tests/Makefile.dep @@ -1,24 +1,23 @@ -t_deriv_image.o: t_deriv_image.cc \ +t_concatenation_creator.o: t_concatenation_creator.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgderimg.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../include/dcmtk/dcmfg/concatenationcreator.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ @@ -115,39 +114,171 @@ t_deriv_image.o: t_deriv_image.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ - ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ - ../include/dcmtk/dcmfg/fg.h ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftempf.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ ../../ofstd/include/dcmtk/ofstd/ofexit.h -t_frame_content.o: t_frame_content.cc \ +t_concatenation_loader.o: t_concatenation_loader.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmfg/fgfracon.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../include/dcmtk/dcmfg/concatenationloader.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../ofstd/include/dcmtk/ofstd/ofstrutl.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_ct_acquisition_details.o: t_ct_acquisition_details.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgctacquisitiondetails.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ @@ -246,11 +377,904 @@ t_frame_content.o: t_frame_content.cc \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmfg/fg.h ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_ct_acquisition_type.o: t_ct_acquisition_type.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgctacquisitiontype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_ct_image_frame_type.o: t_ct_image_frame_type.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgctimageframetype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_ct_position.o: t_ct_position.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgctposition.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_ct_table_dynamics.o: t_ct_table_dynamics.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgcttabledynamics.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_deriv_image.o: t_deriv_image.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgderimg.h ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmfg/fginterface.h ../include/dcmtk/dcmfg/fg.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_frame_content.o: t_frame_content.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fginterface.h \ + ../include/dcmtk/dcmfg/fg.h ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h +t_irradiation_event_identification.o: \ + t_irradiation_event_identification.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fginterface.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fg.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmfg/fgirradiationeventid.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ diff --git a/dcmfg/tests/Makefile.in b/dcmfg/tests/Makefile.in index 4f6c0763..4de62612 100644 --- a/dcmfg/tests/Makefile.in +++ b/dcmfg/tests/Makefile.in @@ -22,9 +22,21 @@ LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ LOCALLIBS = -ldcmfg -ldcmiod -ldcmdata -loflog -lofstd $(ZLIBLIBS) \ $(CHARCONVLIBS) $(MATHLIBS) LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include \ - -I$(dcmdatadir)/include -I$(dcmioddir)/include \ + -I$(dcmdatadir)/include -I$(dcmioddir)/include + +test_objs = t_concatenation_creator.o \ + t_concatenation_loader.o \ + t_ct_acquisition_details.o \ + t_ct_acquisition_type.o \ + t_ct_image_frame_type.o \ + t_ct_position.o \ + t_ct_table_dynamics.o \ + t_deriv_image.o \ + t_frame_content.o \ + t_irradiation_event_identification.o \ + tests.o + -test_objs = tests.o t_deriv_image.o t_frame_content.o objs = $(test_objs) progs = tests @@ -36,10 +48,10 @@ tests: $(test_objs) check: tests - ./tests + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests check-exhaustive: tests - ./tests -x + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests -x install: all diff --git a/dcmfg/tests/t_concatenation_creator.cc b/dcmfg/tests/t_concatenation_creator.cc new file mode 100644 index 00000000..cdf8e9d3 --- /dev/null +++ b/dcmfg/tests/t_concatenation_creator.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for ConcatenationCreator class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/oftempf.h" +#include "dcmtk/ofstd/oftest.h" + +// NEMA CT Test files are available at: +// ftp://medical.nema.org/medical/dicom/Multiframe/CT/nemamfct.images.tar.bz2 +static OFString NEMA_ENHANCED_CT_DIR = "/home/michael/Downloads/NEMA/DISCIMG/IMAGES/"; +static OFString CT1 = NEMA_ENHANCED_CT_DIR + PATH_SEPARATOR + "CT0001"; + +OFTEST(dcmfg_concatenation_creator) +{ + if (!OFStandard::fileExists(CT1)) + return; + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(CT1); + ConcatenationCreator cc; + result = cc.setCfgInput(dcmff.getDataset(), OFFalse /* do not take ownership */); + OFCHECK(result.good()); + if (result.good()) + { + size_t numInstances = cc.getNumInstances(); + OFCHECK(numInstances == 3); + for (size_t i = 0; result.good() && (i < numInstances); i++) + { + DcmFileFormat destff; + result = cc.writeNextInstance(*(destff.getDataset())); + OFCHECK(result.good()); + if (result.good()) + { + OFTempFile tf(O_RDWR, "", "", ".dcm"); + result = destff.saveFile(tf.getFilename(), EXS_LittleEndianExplicit); + OFCHECK(result.good()); + } + } + } +} + +OFTEST(dcmfg_concatenation_creator_fail) +{ + if (!OFStandard::fileExists(CT1)) + return; + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(CT1); + ConcatenationCreator cc; + cc.setCfgFramesPerInstance(55); + result = cc.setCfgInput(dcmff.getDataset(), OFFalse /* do not take ownership */); + OFCHECK(result.good()); + OFTempFile tf(O_RDWR, "", "", ".dcm"); + result = cc.writeNextInstance(tf.getFilename()); + OFCHECK(result == FG_EC_NotEnoughFrames); +} diff --git a/dcmfg/tests/t_concatenation_loader.cc b/dcmfg/tests/t_concatenation_loader.cc new file mode 100644 index 00000000..c8d974c9 --- /dev/null +++ b/dcmfg/tests/t_concatenation_loader.cc @@ -0,0 +1,3149 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for Concatenation Creator class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstrutl.h" +#include "dcmtk/ofstd/oftest.h" + +// Path to NEMA example data with trailing slash +static OFString NEMA_ENHANCED_CT_DIR = "/home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/"; +static OFString SCAN_DUMP, DSET_DUMP; + +static void prepare_scan_dump(); +static void prepare_dset_dump(); +static void check_dump(const OFString& expected, const OFString& output); + +OFTEST(dcmfg_concatenation_loader) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + if (!OFStandard::dirExists(NEMA_ENHANCED_CT_DIR)) + return; + + prepare_scan_dump(); + prepare_dset_dump(); + + // Scan directory and check that result is expected + ConcatenationLoader cl; + cl.setIgnoreMissingSourceUID(OFTrue); // NEMA test data misses this attribute... + OFCondition result = cl.scan(NEMA_ENHANCED_CT_DIR); + OFCHECK(result.good()); + const ConcatenationLoader::TScanResult& concats = cl.getInfo(); + OFCHECK(concats.size() == 3); + OFStringStream out; + ConcatenationLoader::TScanResult::const_iterator it = concats.begin(); + while (it != concats.end()) + { + (*it).second->print(out); + it++; + if (it != concats.end()) + { + out << "--------------------------------------------------------------" << OFendl; + } + } + check_dump(SCAN_DUMP, out.str().c_str()); + + ConcatenationLoader::TScanFailures failed = cl.getFailedFiles(); + ConcatenationLoader::TScanFailureIt ff = failed.begin(); + while (ff != failed.end()) + { + // Filename is set + OFCHECK(!(*ff).fname.isEmpty()); + // Error is set accordingly + OFCHECK((*ff).errorText == "File is not part of Concatenation"); + // SOP Instance UID is set and valid + DcmUniqueIdentifier::checkStringValue((*ff).sopInstance, "1"); + ff++; + } + // Scanning done, now load + + DcmFileFormat dcmff; + OFVector frames; + result = cl.load("1.3.6.1.4.1.5962.1.7.70.2.1.1166562673.14401", dcmff.getDataset(), frames); + OFCHECK(result.good()); + if (result.good()) + { + // Patch in expected values stored in pre-defined dump. In input concatenation, + // SOP Instance UID of Concatenation Source is missing so the conversion will create + // a new SOP Instance UID for the merged dataset. + OFCHECK(dcmff.getDataset()->putAndInsertOFStringArray(DCM_ContentDate, "20191009").good()); + OFCHECK(dcmff.getDataset()->putAndInsertOFStringArray(DCM_ContentTime, "154326").good()); + OFCHECK(dcmff.getDataset() + ->putAndInsertOFStringArray(DCM_SOPInstanceUID, "1.3.6.1.4.1.5962.1.7.70.2.1.1166562673.14401") + .good()); + OFStringStream s; + dcmff.getDataset()->print(s); + check_dump(DSET_DUMP, s.str().c_str()); + } + + DcmIODUtil::freeContainer(frames); +} + +static void prepare_scan_dump() +{ + SCAN_DUMP += "Concatenation UID* : 1.3.6.1.4.1.5962.1.7.70.2.1.1166562673.14401\n"; + SCAN_DUMP += " SOP Class UID* : 1.2.840.10008.5.1.4.1.1.2.1\n"; + SCAN_DUMP += " Concatentation Source UID* : \n"; + SCAN_DUMP += " Concatentation Source File : \n"; + SCAN_DUMP += " Number of Frames (computed): 60\n"; + SCAN_DUMP += " In-conc. Total Number : 6\n"; + SCAN_DUMP += " Patient ID : 0070\n"; + SCAN_DUMP += " Study Instance UID* : 1.3.6.1.4.1.5962.1.2.70.1166562673.14401\n"; + SCAN_DUMP += " Series Instance UID* : 1.3.6.1.4.1.5962.1.3.70.2.1166562673.14401\n"; + SCAN_DUMP += " Bits Allocated* : 16\n"; + SCAN_DUMP += " Rows* : 512\n"; + SCAN_DUMP += " Columns* : 512\n"; + SCAN_DUMP += " Files: \n"; + SCAN_DUMP += " 1. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_1\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.1.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 1\n"; + SCAN_DUMP += " 2. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_2\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.2.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 2\n"; + SCAN_DUMP += " 3. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_3\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.3.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 3\n"; + SCAN_DUMP += " 4. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_4\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.4.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 4\n"; + SCAN_DUMP += " 5. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_5\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.5.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 5\n"; + SCAN_DUMP += " 6. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0074_6\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.1.6.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 6\n"; + SCAN_DUMP += "--------------------------------------------------------------\n"; + SCAN_DUMP += "Concatenation UID* : 1.3.6.1.4.1.5962.1.7.70.2.2.1166562673.14401\n"; + SCAN_DUMP += " SOP Class UID* : 1.2.840.10008.5.1.4.1.1.2.1\n"; + SCAN_DUMP += " Concatentation Source UID* : \n"; + SCAN_DUMP += " Concatentation Source File : \n"; + SCAN_DUMP += " Number of Frames (computed): 30\n"; + SCAN_DUMP += " In-conc. Total Number : 3\n"; + SCAN_DUMP += " Patient ID : 0070\n"; + SCAN_DUMP += " Study Instance UID* : 1.3.6.1.4.1.5962.1.2.70.1166562673.14401\n"; + SCAN_DUMP += " Series Instance UID* : 1.3.6.1.4.1.5962.1.3.70.2.1166562673.14401\n"; + SCAN_DUMP += " Bits Allocated* : 16\n"; + SCAN_DUMP += " Rows* : 512\n"; + SCAN_DUMP += " Columns* : 512\n"; + SCAN_DUMP += " Files: \n"; + SCAN_DUMP += " 1. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0075_1\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.2.1.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 1\n"; + SCAN_DUMP += " 2. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0075_2\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.2.2.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 2\n"; + SCAN_DUMP += " 3. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0075_3\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.2.3.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 3\n"; + SCAN_DUMP += "--------------------------------------------------------------\n"; + SCAN_DUMP += "Concatenation UID* : 1.3.6.1.4.1.5962.1.7.70.2.3.1166562673.14401\n"; + SCAN_DUMP += " SOP Class UID* : 1.2.840.10008.5.1.4.1.1.2.1\n"; + SCAN_DUMP += " Concatentation Source UID* : \n"; + SCAN_DUMP += " Concatentation Source File : \n"; + SCAN_DUMP += " Number of Frames (computed): 30\n"; + SCAN_DUMP += " In-conc. Total Number : 3\n"; + SCAN_DUMP += " Patient ID : 0070\n"; + SCAN_DUMP += " Study Instance UID* : 1.3.6.1.4.1.5962.1.2.70.1166562673.14401\n"; + SCAN_DUMP += " Series Instance UID* : 1.3.6.1.4.1.5962.1.3.70.2.1166562673.14401\n"; + SCAN_DUMP += " Bits Allocated* : 16\n"; + SCAN_DUMP += " Rows* : 512\n"; + SCAN_DUMP += " Columns* : 512\n"; + SCAN_DUMP += " Files: \n"; + SCAN_DUMP += " 1. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0076_1\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.3.1.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 1\n"; + SCAN_DUMP += " 2. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0076_2\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.3.2.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 2\n"; + SCAN_DUMP += " 3. /home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/CT0076_3\n"; + SCAN_DUMP += " SOP Instance UID: 1.3.6.1.4.1.5962.1.1.70.2.3.3.1166562673.14401\n"; + SCAN_DUMP += " Number of Frames: 10\n"; + SCAN_DUMP += " In-Concatenation Frame Offset Number: 3\n"; + + OFStringUtil::replace_all(SCAN_DUMP, "/home/michael/data/dcm/nema_mf/DISCIMG/IMAGES/", NEMA_ENHANCED_CT_DIR); +} + +static void prepare_dset_dump() +{ + DSET_DUMP += "\n"; + DSET_DUMP += "# Dicom-Data-Set\n"; + DSET_DUMP += "# Used TransferSyntax: Little Endian Explicit\n"; + DSET_DUMP += "(0008,0005) CS [ISO_IR 100] # 10, 1 SpecificCharacterSet\n"; + DSET_DUMP += "(0008,0008) CS [ORIGINAL\\PRIMARY\\POST_CONTRAST\\NONE] # 36, 4 ImageType\n"; + DSET_DUMP += "(0008,0012) DA [20061219] # 8, 1 InstanceCreationDate\n"; + DSET_DUMP += "(0008,0013) TM [205025] # 6, 1 InstanceCreationTime\n"; + DSET_DUMP += "(0008,0014) UI [1.3.6.1.4.1.5962.3] # 18, 1 InstanceCreatorUID\n"; + DSET_DUMP += "(0008,0016) UI =EnhancedCTImageStorage # 28, 1 SOPClassUID\n"; + DSET_DUMP += "(0008,0018) UI [1.3.6.1.4.1.5962.1.7.70.2.1.1166562673.14401] # 44, 1 SOPInstanceUID\n"; + DSET_DUMP += "(0008,0020) DA [20061219] # 8, 1 StudyDate\n"; + DSET_DUMP += "(0008,0021) DA [20061219] # 8, 1 SeriesDate\n"; + DSET_DUMP += "(0008,0023) DA [20191009] # 8, 1 ContentDate\n"; + DSET_DUMP += "(0008,002a) DT [20061219204055] # 14, 1 AcquisitionDateTime\n"; + DSET_DUMP += "(0008,0030) TM [203523] # 6, 1 StudyTime\n"; + DSET_DUMP += "(0008,0031) TM [204010] # 6, 1 SeriesTime\n"; + DSET_DUMP += "(0008,0033) TM [154326] # 6, 1 ContentTime\n"; + DSET_DUMP += "(0008,0050) SH [0070] # 4, 1 AccessionNumber\n"; + DSET_DUMP += "(0008,0060) CS [CT] # 2, 1 Modality\n"; + DSET_DUMP += "(0008,0070) LO [Acme Medical Devices] # 20, 1 Manufacturer\n"; + DSET_DUMP += "(0008,0080) LO [St. Nowhere Hospital] # 20, 1 InstitutionName\n"; + DSET_DUMP += "(0008,0090) PN [Thomas^Albert] # 14, 1 ReferringPhysicianName\n"; + DSET_DUMP += "(0008,0201) SH [-0400] # 6, 1 TimezoneOffsetFromUTC\n"; + DSET_DUMP += "(0008,1010) SH [CONSOLE01] # 10, 1 StationName\n"; + DSET_DUMP += "(0008,1030) LO (no value available) # 0, 0 StudyDescription\n"; + DSET_DUMP += "(0008,103e) LO [Shared dimensions and stacks across series and concatenations] # 62, 1 " + "SeriesDescription\n"; + DSET_DUMP += "(0008,1050) PN [Smith^John] # 10, 1 PerformingPhysicianName\n"; + DSET_DUMP += "(0008,1060) PN [Smith^John] # 10, 1 NameOfPhysiciansReadingStudy\n"; + DSET_DUMP += "(0008,1070) PN [Jones^Molly] # 12, 1 OperatorsName\n"; + DSET_DUMP += "(0008,1090) LO [Super Dooper Scanner] # 20, 1 ManufacturerModelName\n"; + DSET_DUMP += "(0008,9121) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedRawDataSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,1115) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedSeriesSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,1199) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedSOPSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,1150) UI =RawDataStorage # 26, 1 ReferencedSOPClassUID\n"; + DSET_DUMP += " (0008,1155) UI [1.3.6.1.4.1.5962.1.9.70.2.1166562673.14401] # 42, 1 " + "ReferencedSOPInstanceUID\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,000e) UI [1.3.6.1.4.1.5962.1.3.70.2.1166562673.14401] # 42, 1 SeriesInstanceUID\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,000d) UI [1.3.6.1.4.1.5962.1.2.70.1166562673.14401] # 40, 1 StudyInstanceUID\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + DSET_DUMP += "(0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + DSET_DUMP += "(0008,9207) CS [NONE] # 4, 1 VolumeBasedCalculationTechnique\n"; + DSET_DUMP += "(0010,0010) PN [ChestAbdoPelvis^MultiphaseLiver] # 32, 1 PatientName\n"; + DSET_DUMP += "(0010,0020) LO [0070] # 4, 1 PatientID\n"; + DSET_DUMP += "(0010,0030) DA [19500704] # 8, 1 PatientBirthDate\n"; + DSET_DUMP += "(0010,0040) CS [M] # 2, 1 PatientSex\n"; + DSET_DUMP += "(0010,1010) AS [052Y] # 4, 1 PatientAge\n"; + DSET_DUMP += "(0010,1020) DS [1.6] # 4, 1 PatientSize\n"; + DSET_DUMP += "(0010,1030) DS [75] # 2, 1 PatientWeight\n"; + DSET_DUMP += "(0018,0012) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusAgentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=8) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [C-B0322] # 8, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SRT] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Iohexol] # 8, 1 CodeMeaning\n"; + DSET_DUMP += " (0018,0014) SQ (Sequence with undefined length #=1) # u/l, 1 " + "ContrastBolusAdministrationRouteSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [G-D101] # 6, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SNM3] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Intravenous route] # 18, 1 CodeMeaning\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,1041) DS [150] # 4, 1 ContrastBolusVolume\n"; + DSET_DUMP += " (0018,1049) DS [300] # 4, 1 " + "ContrastBolusIngredientConcentration\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9338) SQ (Sequence with undefined length #=1) # u/l, 1 ContrastBolusIngredientCodeSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [C-11400] # 8, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SRT] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Iodine] # 6, 1 CodeMeaning\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=8) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [C-B0317] # 8, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SNM3] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Diatrizoate] # 12, 1 CodeMeaning\n"; + DSET_DUMP += " (0018,0014) SQ (Sequence with undefined length #=1) # u/l, 1 " + "ContrastBolusAdministrationRouteSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [G-D140] # 6, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SNM3] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Oral route] # 10, 1 CodeMeaning\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,1041) DS [1000] # 4, 1 ContrastBolusVolume\n"; + DSET_DUMP += " (0018,1049) DS [11.1] # 4, 1 " + "ContrastBolusIngredientConcentration\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9338) SQ (Sequence with undefined length #=1) # u/l, 1 ContrastBolusIngredientCodeSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [C-11400] # 8, 1 CodeValue\n"; + DSET_DUMP += " (0008,0102) SH [SRT] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Iodine] # 6, 1 CodeMeaning\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(0018,1000) LO [123456] # 6, 1 DeviceSerialNumber\n"; + DSET_DUMP += "(0018,1020) LO [1.00] # 4, 1 SoftwareVersions\n"; + DSET_DUMP += "(0018,5100) CS [FFS] # 4, 1 PatientPosition\n"; + DSET_DUMP += "(0018,9004) CS [PRODUCT] # 8, 1 ContentQualification\n"; + DSET_DUMP += "(0018,9073) FD 522.00048828124988631 # 8, 1 AcquisitionDuration\n"; + DSET_DUMP += "(0020,000d) UI [1.3.6.1.4.1.5962.1.2.70.1166562673.14401] # 40, 1 StudyInstanceUID\n"; + DSET_DUMP += "(0020,000e) UI [1.3.6.1.4.1.5962.1.3.70.2.1166562673.14401] # 42, 1 SeriesInstanceUID\n"; + DSET_DUMP += "(0020,0010) SH [0070] # 4, 1 StudyID\n"; + DSET_DUMP += "(0020,0011) IS [2] # 2, 1 SeriesNumber\n"; + DSET_DUMP += "(0020,0012) IS [2] # 2, 1 AcquisitionNumber\n"; + DSET_DUMP += "(0020,0013) IS [1] # 2, 1 InstanceNumber\n"; + DSET_DUMP += "(0020,0052) UI [1.3.6.1.4.1.5962.1.4.70.1.1166562673.14401] # 42, 1 FrameOfReferenceUID\n"; + DSET_DUMP += "(0020,1040) LO [XY] # 2, 1 PositionReferenceIndicator\n"; + DSET_DUMP += "(0020,4000) LT [Both arterial and portal venous] # 32, 1 ImageComments\n"; + DSET_DUMP += "(0020,9221) SQ (Sequence with undefined length #=1) # u/l, 1 DimensionOrganizationSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP + += " (0020,9164) UI [1.3.6.1.4.1.5962.1.6.70.2.0.1166562673.14401] # 44, 1 DimensionOrganizationUID\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(0020,9222) SQ (Sequence with undefined length #=3) # u/l, 1 DimensionIndexSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP + += " (0020,9164) UI [1.3.6.1.4.1.5962.1.6.70.2.0.1166562673.14401] # 44, 1 DimensionOrganizationUID\n"; + DSET_DUMP += " (0020,9165) AT (0020,9056) # 4, 1 DimensionIndexPointer\n"; + DSET_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP + += " (0020,9164) UI [1.3.6.1.4.1.5962.1.6.70.2.0.1166562673.14401] # 44, 1 DimensionOrganizationUID\n"; + DSET_DUMP += " (0020,9165) AT (0020,9057) # 4, 1 DimensionIndexPointer\n"; + DSET_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP + += " (0020,9164) UI [1.3.6.1.4.1.5962.1.6.70.2.0.1166562673.14401] # 44, 1 DimensionOrganizationUID\n"; + DSET_DUMP += " (0020,9165) AT (0018,9344) # 4, 1 DimensionIndexPointer\n"; + DSET_DUMP += " (0020,9167) AT (0018,9341) # 4, 1 FunctionalGroupPointer\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(0028,0002) US 1 # 2, 1 SamplesPerPixel\n"; + DSET_DUMP += "(0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation\n"; + DSET_DUMP += "(0028,0008) IS [60] # 2, 1 NumberOfFrames\n"; + DSET_DUMP += "(0028,0010) US 512 # 2, 1 Rows\n"; + DSET_DUMP += "(0028,0011) US 512 # 2, 1 Columns\n"; + DSET_DUMP += "(0028,0100) US 16 # 2, 1 BitsAllocated\n"; + DSET_DUMP += "(0028,0101) US 16 # 2, 1 BitsStored\n"; + DSET_DUMP += "(0028,0102) US 15 # 2, 1 HighBit\n"; + DSET_DUMP += "(0028,0103) US 1 # 2, 1 PixelRepresentation\n"; + DSET_DUMP += "(0028,0301) CS [NO] # 2, 1 BurnedInAnnotation\n"; + DSET_DUMP += "(0028,2110) CS [00] # 2, 1 LossyImageCompression\n"; + DSET_DUMP += "(0040,0555) SQ (Sequence with undefined length #=0) # u/l, 1 AcquisitionContextSequence\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(2050,0020) CS [IDENTITY] # 8, 1 PresentationLUTShape\n"; + DSET_DUMP += "(5200,9229) SQ (Sequence with undefined length #=1) # u/l, 1 SharedFunctionalGroupsSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=14) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9301) SQ (Sequence with undefined length #=1) # u/l, 1 CTAcquisitionTypeSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9302) CS [SPIRAL] # 6, 1 AcquisitionType\n"; + DSET_DUMP += " (0018,9333) CS [NO] # 2, 1 ConstantVolumeFlag\n"; + DSET_DUMP += " (0018,9334) CS [NO] # 2, 1 FluoroscopyFlag\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9304) SQ (Sequence with undefined length #=1) # u/l, 1 CTAcquisitionDetailsSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,0090) DS [480.000] # 8, 1 DataCollectionDiameter\n"; + DSET_DUMP += " (0018,1120) DS [0.00000] # 8, 1 GantryDetectorTilt\n"; + DSET_DUMP += " (0018,1130) DS [103.200] # 8, 1 TableHeight\n"; + DSET_DUMP += " (0018,1140) CS [CW] # 2, 1 RotationDirection\n"; + DSET_DUMP += " (0018,9305) FD 1 # 8, 1 RevolutionTime\n"; + DSET_DUMP += " (0018,9306) FD 7.000007629394530361822 # 8, 1 SingleCollimationWidth\n"; + DSET_DUMP += " (0018,9307) FD 7.000007629394530361822 # 8, 1 TotalCollimationWidth\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9308) SQ (Sequence with undefined length #=1) # u/l, 1 CTTableDynamicsSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9309) FD 9.8000183105468732 # 8, 1 TableSpeed\n"; + DSET_DUMP += " (0018,9310) FD 9.800010681152342 # 8, 1 TableFeedPerRotation\n"; + DSET_DUMP += " (0018,9311) FD 1.4000015258789061 # 8, 1 SpiralPitchFactor\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9312) SQ (Sequence with undefined length #=1) # u/l, 1 CTGeometrySequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,1110) DS [1099.31] # 8, 1 DistanceSourceToDetector\n"; + DSET_DUMP += " (0018,9335) FD 630.00048828124988631 # 8, 1 " + "DistanceSourceToDataCollectionCenter\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9314) SQ (Sequence with undefined length #=1) # u/l, 1 CTReconstructionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,1100) DS [325.000] # 8, 1 ReconstructionDiameter\n"; + DSET_DUMP += " (0018,1210) SH [STANDARD] # 8, 1 ConvolutionKernel\n"; + DSET_DUMP += " (0018,9315) CS [ITERATIVE] # 10, 1 ReconstructionAlgorithm\n"; + DSET_DUMP += " (0018,9316) CS [SOFT_TISSUE] # 12, 1 ConvolutionKernelGroup\n"; + DSET_DUMP += " (0018,9319) FD 360.00024414062494316 # 8, 1 ReconstructionAngle\n"; + DSET_DUMP += " (0018,9320) SH [None] # 4, 1 ImageFilter\n"; + DSET_DUMP + += " (0018,9322) FD 0.63476610183715811\\0.63476610183715811 # 16, 2 ReconstructionPixelSpacing\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9321) SQ (Sequence with undefined length #=1) # u/l, 1 CTExposureSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=5) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9323) CS [NONE] # 4, 1 ExposureModulationType\n"; + DSET_DUMP += " (0018,9328) FD 1000.0004882812498863 # 8, 1 ExposureTimeInms\n"; + DSET_DUMP += " (0018,9330) FD 230.00012207031247158 # 8, 1 XRayTubeCurrentInmA\n"; + DSET_DUMP += " (0018,9332) FD 230.00012207031247158 # 8, 1 ExposureInmAs\n"; + DSET_DUMP += " (0018,9345) FD (no value available) # 0, 0 CTDIvol\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9325) SQ (Sequence with undefined length #=1) # u/l, 1 CTXRayDetailsSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,0060) DS [120.000] # 8, 1 KVP\n"; + DSET_DUMP += " (0018,1160) SH [WEDGE] # 6, 1 FilterType\n"; + DSET_DUMP += " (0018,1190) DS [1.20000] # 8, 1 FocalSpots\n"; + DSET_DUMP += " (0018,7050) CS [MIXED] # 6, 1 FilterMaterial\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9329) SQ (Sequence with undefined length #=1) # u/l, 1 CTImageFrameTypeSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,9007) CS [ORIGINAL\\PRIMARY\\POST_CONTRAST\\NONE] # 36, 4 FrameType\n"; + DSET_DUMP += " (0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + DSET_DUMP += " (0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + DSET_DUMP + += " (0008,9207) CS [NONE] # 4, 1 VolumeBasedCalculationTechnique\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9477) SQ (Sequence with undefined length #=1) # u/l, 1 " + "IrradiationEventIdentificationSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP + += " (0008,3010) UI [1.3.6.1.4.1.5962.1.10.70.2.1.1166562673.14401] # 46, 1 IrradiationEventUID\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9071) SQ (Sequence with undefined length #=1) # u/l, 1 FrameAnatomySequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,2218) SQ (Sequence with undefined length #=1) # u/l, 1 AnatomicRegionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0008,0100) SH [R-FAB57] # 8, 1 CodeValue\n"; + DSET_DUMP + += " (0008,0102) SH [SRT] # 4, 1 CodingSchemeDesignator\n"; + DSET_DUMP += " (0008,0104) LO [Abdomen and Pelvis] # 18, 1 CodeMeaning\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9072) CS [U] # 2, 1 FrameLaterality\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9116) SQ (Sequence with undefined length #=1) # u/l, 1 PlaneOrientationSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0037) DS [1.00000\\0.00000\\0.00000\\0.00000\\1.00000\\0.00000] # 48, 6 " + "ImageOrientationPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0028,9110) SQ (Sequence with undefined length #=1) # u/l, 1 PixelMeasuresSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,0050) DS [7.00000] # 8, 1 SliceThickness\n"; + DSET_DUMP += " (0028,0030) DS [0.634766\\0.634766] # 18, 2 PixelSpacing\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0028,9132) SQ (Sequence with undefined length #=1) # u/l, 1 FrameVOILUTSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item\n"; + DSET_DUMP += " (0028,1050) DS [40.0000] # 8, 1 WindowCenter\n"; + DSET_DUMP += " (0028,1051) DS [400.000] # 8, 1 WindowWidth\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP + += " (0028,9145) SQ (Sequence with undefined length #=1) # u/l, 1 PixelValueTransformationSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0028,1052) DS [-1024.00] # 8, 1 RescaleIntercept\n"; + DSET_DUMP += " (0028,1053) DS [1.00000] # 8, 1 RescaleSlope\n"; + DSET_DUMP += " (0028,1054) LO [HU] # 2, 1 RescaleType\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += "(5200,9230) SQ (Sequence with undefined length #=60) # u/l, 1 PerFrameFunctionalGroupsSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-10.00000762939452947364 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-10.00000762939452947364 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -10.00000762939452947364 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204055] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204055.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 30 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\30\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-10.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-17.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-17.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -17.00143432617187145 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204055.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204056.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 29 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\29\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-17.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-24.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-24.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -24.00285339355468395 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204056.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204056.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 28 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\28\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-24.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-31.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-31.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -31.00427246093749645 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204057.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204057.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 27 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\27\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-31.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-38.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-38.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -37.995758056640618 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204057.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204058.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 26 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\26\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-38.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-45.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-45.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -44.997161865234368 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204058.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204058.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 25 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\25\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-45.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-52.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-52.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -51.998596191406243 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204059.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204059.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 24 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\24\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-52.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-59.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-59.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -59.0000305175781178946 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204100] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204100.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 23 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\23\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-59.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-66.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-66.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -66.00146484374998579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204100.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204101.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 22 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\22\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-66.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-73.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-73.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -73.00286865234373579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204101.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204101.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 21 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\21\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-73.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-80.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-80.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -80.00433349609373579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204102.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204102.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 20 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\20\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-80.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-87.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-87.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -86.995788574218736 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204102.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204103.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 19 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\19\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-87.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-94.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-94.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -93.997192382812486 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204103.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204103.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 18 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\18\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-94.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-101.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-101.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -100.99859619140624 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204104.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204104.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 17 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\17\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-101.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-108.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-108.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -108.000061035156235789 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204105] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204105.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 16 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\16\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-108.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-115.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-115.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -115.0014648437499858 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204105.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204106.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 15 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\15\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-115.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-122.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-122.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -122.0028686523437358 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204106.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204106.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 14 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\14\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-122.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-129.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-129.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -129.0043945312499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204107.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204107.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 13 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\13\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-129.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-136.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-136.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -135.99584960937497 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204107.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204108.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 12 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\12\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-136.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-143.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-143.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -142.99719238281247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204108.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204108.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 11 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\11\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-143.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-150.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-150.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -149.99865722656247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204109.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204109.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 10 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\10\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-150.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-157.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-157.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -157.00012207031247158 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204109.999] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204110.349] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 9 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\9\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-157.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-164.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-164.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -164.0014648437499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204110.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204111.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 8 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\8\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-164.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-171.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-171.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -171.0029296874999716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204111.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204111.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 7 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\7\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-171.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-178.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-178.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -178.0043945312499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204112.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204112.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 6 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\6\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-178.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-185.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-185.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -184.99584960937497 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204112.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204113.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 5 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\5\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-185.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-192.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-192.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -191.99719238281247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204113.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204113.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 4 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\4\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-192.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-199.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-199.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -198.99865722656247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204114.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204114.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 3 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\3\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-199.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-206.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-206.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -206.00012207031247158 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204115] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204115.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 2 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\2\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-206.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-213.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-213.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -213.0014648437499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [ARTERIAL] # 8, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204115.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204116.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 1 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\1\\1 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-213.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-10.00000762939452947364 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-10.00000762939452947364 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -10.00000762939452947364 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204137] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204137.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 30 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\30\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-10.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-17.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-17.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -17.00143432617187145 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204137.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204138.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 29 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\29\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-17.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-24.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-24.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -24.00285339355468395 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204138.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204138.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 28 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\28\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-24.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-31.0000152587890589473 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-31.0000152587890589473 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -31.00427246093749645 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204139.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204139.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 27 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\27\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-31.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-38.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-38.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -37.995758056640618 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204139.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204140.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 26 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\26\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-38.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-45.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-45.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -44.997161865234368 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204140.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204140.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 25 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\25\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-45.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-52.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-52.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -51.998596191406243 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204141.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204141.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 24 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\24\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-52.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-59.0000305175781178946 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-59.0000305175781178946 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -59.0000305175781178946 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204142] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204142.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 23 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\23\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-59.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-66.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-66.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -66.00146484374998579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204142.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204143.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 22 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\22\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-66.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-73.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-73.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -73.00286865234373579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204143.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204143.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 21 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\21\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-73.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-80.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-80.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -80.00433349609373579 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204144.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204144.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 20 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\20\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-80.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-87.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-87.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -86.995788574218736 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204144.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204145.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 19 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\19\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-87.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-94.0000610351562357891 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-94.0000610351562357891 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -93.997192382812486 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204145.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204145.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 18 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\18\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-94.0000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-101.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-101.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -100.99859619140624 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204146.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204146.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 17 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\17\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-101.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-108.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-108.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -108.000061035156235789 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204147] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204147.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 16 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\16\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-108.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-115.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-115.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -115.0014648437499858 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204147.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204148.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 15 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\15\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-115.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-122.000061035156235789 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-122.000061035156235789 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -122.0028686523437358 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204148.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204148.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 14 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\14\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-122.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-129.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-129.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -129.0043945312499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204149.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204149.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 13 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\13\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-129.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-136.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-136.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -135.99584960937497 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204149.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204150.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 12 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\12\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-136.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-143.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-143.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -142.99719238281247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204150.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204150.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 11 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\11\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-143.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-150.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-150.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -149.99865722656247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204151.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204151.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 10 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\10\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-150.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-157.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-157.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -157.00012207031247158 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204151.999] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204152.349] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 9 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\9\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-157.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-164.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-164.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -164.0014648437499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204152.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204153.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 8 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\8\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-164.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-171.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-171.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -171.0029296874999716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204153.428] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204153.778] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 7 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\7\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-171.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-178.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-178.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -178.0043945312499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204154.142] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204154.492] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 6 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\6\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-178.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-185.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-185.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -184.99584960937497 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204154.857] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204155.207] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 5 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\5\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-185.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-192.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-192.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -191.99719238281247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204155.571] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204155.921] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 4 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\4\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-192.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-199.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-199.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -198.99865722656247 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204156.285] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204156.635] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 3 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\3\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-199.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-206.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-206.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -206.00012207031247158 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204157] # 14, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204157.350] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 2 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\2\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-206.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9313) FD 3.08271408081054643\\-0.31728720664978023\\-213.00012207031247158 # 24, 3 " + "DataCollectionCenterPatient\n"; + DSET_DUMP += " (0018,9318) FD 3.08271408081054643\\-0.31728720664978023\\-213.00012207031247158 # 24, 3 " + "ReconstructionTargetCenterPatient\n"; + DSET_DUMP += " (0018,9327) FD -213.0014648437499716 # 8, 1 TablePosition\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 1 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS [YES] # 4, 1 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (0018,9344) CS [PORTAL_VENOUS] # 14, 1 ContrastBolusAgentPhase\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9337) US 2 # 2, 1 ContrastBolusAgentNumber\n"; + DSET_DUMP + += " (0018,9342) CS [YES] # 4, 1 ContrastBolusAgentAdministered\n"; + DSET_DUMP + += " (0018,9343) CS (no value available) # 0, 0 ContrastBolusAgentDetected\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9111) SQ (Sequence with undefined length #=1) # u/l, 1 FrameContentSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=7) # u/l, 1 Item\n"; + DSET_DUMP += " (0018,9074) DT [20061219204157.714] # 18, 1 FrameAcquisitionDateTime\n"; + DSET_DUMP += " (0018,9151) DT [20061219204158.064] # 18, 1 FrameReferenceDateTime\n"; + DSET_DUMP += " (0018,9220) FD 700.00048828124988631 # 8, 1 FrameAcquisitionDuration\n"; + DSET_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + DSET_DUMP += " (0020,9057) UL 1 # 4, 1 InStackPositionNumber\n"; + DSET_DUMP += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + DSET_DUMP += " (0020,9157) UL 1\\1\\2 # 12, 3 DimensionIndexValues\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence\n"; + DSET_DUMP += " (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item\n"; + DSET_DUMP += " (0020,0032) DS [-159.100\\-162.500\\-213.000] # 26, 3 ImagePositionPatient\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; + DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n"; + DSET_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n"; +} + +void check_dump(const OFString& expected, const OFString& output) +{ + OFBool matches = (expected == output); + OFCHECK(matches); + if (!matches) + { + CERR << "Expected dump:" << OFendl; + CERR << expected << OFendl; + CERR << "Produced dump:" << OFendl; + CERR << output << OFendl; + } +} diff --git a/dcmfg/tests/t_ct_acquisition_details.cc b/dcmfg/tests/t_ct_acquisition_details.cc new file mode 100644 index 00000000..1ee03eea --- /dev/null +++ b/dcmfg/tests/t_ct_acquisition_details.cc @@ -0,0 +1,211 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for CT Acquisition Type FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fgctacquisitiondetails.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void checkDump(const OFString& ds_dump, const OFString& expected_dump); + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += "(0018,9304) SQ (Sequence with explicit length #=2) # 0, 1 CTAcquisitionDetailsSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=8) # 0, 1 Item\n"; + fg_dump += " (0018,0090) DS [6] # 2, 1 DataCollectionDiameter\n"; + fg_dump += " (0018,1120) DS [5] # 2, 1 GantryDetectorTilt\n"; + fg_dump += " (0018,1130) DS [4] # 2, 1 TableHeight\n"; + fg_dump += " (0018,1140) CS [CC] # 2, 1 RotationDirection\n"; + fg_dump += " (0018,9305) FD 1 # 8, 1 RevolutionTime\n"; + fg_dump += " (0018,9306) FD 3 # 8, 1 SingleCollimationWidth\n"; + fg_dump += " (0018,9307) FD 2 # 8, 1 TotalCollimationWidth\n"; + fg_dump += " (0018,9378) US 1\\2\\3 # 6, 3 ReferencedPathIndex\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=8) # 0, 1 Item\n"; + fg_dump += " (0018,0090) DS [12] # 2, 1 DataCollectionDiameter\n"; + fg_dump += " (0018,1120) DS [11] # 2, 1 GantryDetectorTilt\n"; + fg_dump += " (0018,1130) DS [10] # 2, 1 TableHeight\n"; + fg_dump += " (0018,1140) CS [CW] # 2, 1 RotationDirection\n"; + fg_dump += " (0018,9305) FD 7 # 8, 1 RevolutionTime\n"; + fg_dump += " (0018,9306) FD 8 # 8, 1 SingleCollimationWidth\n"; + fg_dump += " (0018,9307) FD 9 # 8, 1 TotalCollimationWidth\n"; + fg_dump += " (0018,9378) US 4\\5\\6 # 6, 3 ReferencedPathIndex\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_ct_acquisition_details_fg(FGCTAcquisitionDetails& fg) +{ + OFCondition result; + OFString val; + OFVector& items = fg.getCTAcquisitionDetailsItems(); + OFCHECK(items.size() == 2); + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* item1 = items[0]; + OFVector vuint; + item1->getReferencedPathIndex(vuint); + OFCHECK(vuint.size() == 3); + OFCHECK((vuint[0] == 1) && (vuint[1] == 2) && (vuint[2] == 3)); + Uint16 u16; + OFCHECK(item1->getReferencedPathIndex(u16, 0).good()); + OFCHECK(u16 == 1); + OFCHECK(item1->getReferencedPathIndex(u16, 1).good()); + OFCHECK(u16 == 2); + OFCHECK(item1->getReferencedPathIndex(u16, 2).good()); + OFCHECK(u16 == 3); + FGCTAcquisitionDetails::E_RotationDirection rot; + OFCHECK(item1->getRotationDirection(rot).good()); + OFCHECK(rot == FGCTAcquisitionDetails::E_RotationDirection_CC); + Float64 f64; + OFCHECK(item1->getRevolutionTime(f64).good()); + OFCHECK(f64 == 1.0); + OFCHECK(item1->getTotalCollimationWidth(f64).good()); + OFCHECK(f64 == 2.0); + OFCHECK(item1->getSingleCollimationWidth(f64).good()); + OFCHECK(f64 == 3.0); + OFCHECK(item1->getTableHeight(f64).good()); + OFCHECK(f64 == 4.0); + OFCHECK(item1->getGantryDetectorTilt(f64).good()); + OFCHECK(f64 == 5.0); + OFCHECK(item1->getDataCollectionDiameter(f64).good()); + OFCHECK(f64 == 6.0); + + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* item2 = items[1]; + vuint.clear(); + item2->getReferencedPathIndex(vuint); + OFCHECK(vuint.size() == 3); + OFCHECK((vuint[0] == 4) && (vuint[1] == 5) && (vuint[2] == 6)); + OFCHECK(item2->getReferencedPathIndex(u16, 0).good()); + OFCHECK(u16 == 4); + OFCHECK(item2->getReferencedPathIndex(u16, 1).good()); + OFCHECK(u16 == 5); + OFCHECK(item2->getReferencedPathIndex(u16, 2).good()); + OFCHECK(u16 == 6); + OFCHECK(item2->getRotationDirection(rot).good()); + OFCHECK(rot == FGCTAcquisitionDetails::E_RotationDirection_CW); + OFCHECK(item2->getRotationDirection(val).good()); + OFCHECK(val == "CW"); + OFCHECK(item2->getRevolutionTime(f64).good()); + OFCHECK(f64 == 7.0); + OFCHECK(item2->getSingleCollimationWidth(f64).good()); + OFCHECK(f64 == 8.0); + OFCHECK(item2->getTotalCollimationWidth(f64).good()); + OFCHECK(f64 == 9.0); + OFCHECK(item2->getTableHeight(f64).good()); + OFCHECK(f64 == 10.0); + OFCHECK(item2->getGantryDetectorTilt(f64).good()); + OFCHECK(f64 == 11.0); + OFCHECK(item2->getDataCollectionDiameter(f64).good()); + OFCHECK(f64 == 12.0); +} + +OFTEST(dcmfg_ct_acquisition_details) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGCTAcquisitionDetails fg; + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* fgi = new FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem; + OFVector vuint; + vuint.push_back(1); + vuint.push_back(2); + vuint.push_back(3); + OFCHECK(fgi->setReferencedPathIndex(vuint).good()); + OFCHECK(fgi->setRotationDirection(FGCTAcquisitionDetails::E_RotationDirection_CC).good()); + OFCHECK(fgi->setRevolutionTime(1.0).good()); + OFCHECK(fgi->setTotalCollimationWidth(2.0).good()); + OFCHECK(fgi->setSingleCollimationWidth(3.0).good()); + OFCHECK(fgi->setTableHeight(4.0).good()); + OFCHECK(fgi->setGantryDetectorTilt(5.0).good()); + OFCHECK(fgi->setDataCollectionDiameter(6.0).good()); + OFVector& items = fg.getCTAcquisitionDetailsItems(); + items.push_back(fgi); + + FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem* fgi2 = fgi->clone(); + vuint.clear(); + vuint.push_back(4); + vuint.push_back(5); + vuint.push_back(6); + OFCHECK(fgi2->setReferencedPathIndex(vuint).good()); + OFCHECK(fgi2->setRotationDirection(FGCTAcquisitionDetails::E_RotationDirection_CW).good()); + OFCHECK(fgi2->setRevolutionTime(7.0).good()); + OFCHECK(fgi2->setSingleCollimationWidth(8.0).good()); + OFCHECK(fgi2->setTotalCollimationWidth(9.0).good()); + OFCHECK(fgi2->setTableHeight(10.0).good()); + OFCHECK(fgi2->setGantryDetectorTilt(11.0).good()); + OFCHECK(fgi2->setDataCollectionDiameter(12.0).good()); + items.push_back(fgi2); + + // Check data structure in memory + check_ct_acquisition_details_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + checkDump(out.str().c_str(), fg_dump); + + // Test read method: Read from dataset, write again, and compare another time + FGCTAcquisitionDetails fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + checkDump(out.str().c_str(), fg_dump); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + OFCHECK(fgi->setTotalCollimationWidth(100.0).good()); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGCTAcquisitionDetails* clone = OFstatic_cast(FGCTAcquisitionDetails*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} + +static void checkDump(const OFString& ds_dump, const OFString& expected_dump) +{ + OFBool dump_ok = (ds_dump == expected_dump); + OFCHECK(dump_ok); + if (!dump_ok) + { + CERR << "Dump produced: " << OFendl << ds_dump << OFendl; + CERR << "------------------------------------" << OFendl; + CERR << "Dump expected: " << OFendl << expected_dump << OFendl; + CERR << "------------------------------------" << OFendl; + } +} diff --git a/dcmfg/tests/t_ct_acquisition_type.cc b/dcmfg/tests/t_ct_acquisition_type.cc new file mode 100644 index 00000000..0751b4d5 --- /dev/null +++ b/dcmfg/tests/t_ct_acquisition_type.cc @@ -0,0 +1,116 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for CT Acquisition Type FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fgctacquisitiontype.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += "(0018,9301) SQ (Sequence with explicit length #=1) # 0, 1 CTAcquisitionTypeSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + fg_dump += " (0018,9302) CS [STATIONARY] # 10, 1 AcquisitionType\n"; + fg_dump += " (0018,9303) FD 0.1234 # 8, 1 TubeAngle\n"; + fg_dump += " (0018,9333) CS [YES] # 4, 1 ConstantVolumeFlag\n"; + fg_dump += " (0018,9334) CS [NO] # 2, 1 FluoroscopyFlag\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_ct_acquisition_type_fg(FGCTAcquisitionType& fg) +{ + OFCondition result; + OFString val; + OFCHECK(fg.getAcquisitionType(val).good()); + OFCHECK(val == "STATIONARY"); + Float64 f64; + OFCHECK(fg.getTubeAngle(f64).good()); + OFCHECK(f64 == 0.1234); + OFCHECK(fg.getConstantVolumeFlag(val).good()); + OFCHECK(val == "YES"); + OFCHECK(fg.getFluoroscopyFlag(val).good()); + OFCHECK(val == "NO"); + + // check enum getters() + FGCTAcquisitionType::E_ConstantVolumeFlag cv; + OFCHECK(fg.getConstantVolumeFlag(cv).good()); + OFCHECK(cv == FGCTAcquisitionType::E_ConstVol_Yes); + + FGCTAcquisitionType::E_FluoroscopyFlag fl; + OFCHECK(fg.getFluoroscopyFlag(fl).good()); + OFCHECK(fl == FGCTAcquisitionType::E_Fluoroscopy_No); +} + +OFTEST(dcmfg_ct_acquisition_type) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGCTAcquisitionType fg; + OFCHECK(fg.setAcquisitionType(FGCTAcquisitionType::DT_AcquisitionType_Stationary).good()); + OFCHECK(fg.setTubeAngle(0.1234).good()); + OFCHECK(fg.setConstantVolumeFlag(FGCTAcquisitionType::E_ConstVol_Yes).good()); + OFCHECK(fg.setFluoroscopyFlag(FGCTAcquisitionType::E_Fluoroscopy_No).good()); + + // Check data structure in memory + check_ct_acquisition_type_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); /**/ + + // Test read method: Read from dataset, write again, and compare another time + FGCTAcquisitionType fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + OFCHECK(fg_for_read.setAcquisitionType(FGCTAcquisitionType::DT_AcquisitionType_ConstantAngle).good()); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGCTAcquisitionType* clone = OFstatic_cast(FGCTAcquisitionType*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} diff --git a/dcmfg/tests/t_ct_image_frame_type.cc b/dcmfg/tests/t_ct_image_frame_type.cc new file mode 100644 index 00000000..badef70d --- /dev/null +++ b/dcmfg/tests/t_ct_image_frame_type.cc @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for CT Image Frame Type FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fgctimageframetype.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += "(0018,9329) SQ (Sequence with explicit length #=1) # 0, 1 CTImageFrameTypeSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + fg_dump += " (0008,9007) CS [ORIGINAL\\PRIMARY\\VOLUME\\NONE] # 28, 4 FrameType\n"; + fg_dump += " (0008,9205) CS [MONOCHROME] # 10, 1 PixelPresentation\n"; + fg_dump += " (0008,9206) CS [VOLUME] # 6, 1 VolumetricProperties\n"; + fg_dump += " (0008,9207) CS [VOLUME_RENDER] # 14, 1 VolumeBasedCalculationTechnique\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_ct_image_frame_type_fg(FGCTImageFrameType& fg) +{ + OFCondition result; + OFString val; + OFCHECK(fg.getFrameType(val, -1 /* all components */).good()); + OFCHECK(val == "ORIGINAL\\PRIMARY\\VOLUME\\NONE"); + OFCHECK(fg.getPixelPresentation(val).good()); + OFCHECK(val == "MONOCHROME"); + OFCHECK(fg.getVolumetricProperties(val).good()); + OFCHECK(val == "VOLUME"); + OFCHECK(fg.getVolumeBasedCalculationTechnique(val).good()); + OFCHECK(val == "VOLUME_RENDER"); + + // Check enum getters + FGCTImageFrameType::E_PixelPresentation pix; + OFCHECK(fg.getPixelPresentation(pix).good()); + OFCHECK(pix == FGCTImageFrameType::E_PixelPres_Monochrome); + + FGCTImageFrameType::E_VolumetricProperties vol; + OFCHECK(fg.getVolumetricProperties(vol).good()); + OFCHECK(vol == FGCTImageFrameType::E_VolProp_Volume); +} + +OFTEST(dcmfg_ct_image_frame_type) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGCTImageFrameType fg; + OFCHECK(fg.setFrameType("ORIGINAL\\PRIMARY\\VOLUME\\NONE").good()); + OFCHECK(fg.setPixelPresentation(FGCTImageFrameType::E_PixelPres_Monochrome).good()); + OFCHECK(fg.setVolumetricProperties(FGCTImageFrameType::E_VolProp_Volume).good()); + OFCHECK(fg.setVolumeBasedCalculationTechnique(FGCTImageFrameType::DT_VolBasedCalcTechnique_VolumeRender).good()); + + // Check data structure in memory + check_ct_image_frame_type_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); /**/ + + // Test read method: Read from dataset, write again, and compare another time + FGCTImageFrameType fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + OFCHECK(fg_for_read.setVolumetricProperties(FGCTImageFrameType::E_VolProp_Distorted).good()); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGCTImageFrameType* clone = OFstatic_cast(FGCTImageFrameType*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} diff --git a/dcmfg/tests/t_ct_position.cc b/dcmfg/tests/t_ct_position.cc new file mode 100644 index 00000000..60a3346f --- /dev/null +++ b/dcmfg/tests/t_ct_position.cc @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for CT Position FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fgctposition.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += "(0018,9326) SQ (Sequence with explicit length #=1) # 0, 1 CTPositionSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + fg_dump += " (0018,9313) FD 1\\2\\3 # 24, 3 DataCollectionCenterPatient\n"; + fg_dump + += " (0018,9318) FD 4\\5\\6 # 24, 3 ReconstructionTargetCenterPatient\n"; + fg_dump += " (0018,9327) FD 1 # 8, 1 TablePosition\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_ct_position_fg(FGCTPosition& fg) +{ + OFCondition result; + OFString val; + OFVector vfl64; + Float64 fl64; + OFCHECK(fg.getTablePosition(fl64).good()); + OFCHECK(fl64 == 1.0); + OFCHECK(fg.getDataCollectionCenterPatient(vfl64).good()); + OFCHECK(vfl64.size() == 3); + OFCHECK(vfl64[0] == 1.0); + OFCHECK(vfl64[1] == 2.0); + OFCHECK(vfl64[2] == 3.0); + OFCHECK(fg.getDataCollectionCenterPatient(val, -1).good()); + OFCHECK(val == "1\\2\\3"); + + vfl64.clear(); + OFCHECK(fg.getReconstructionTargetCenterPatient(vfl64).good()); + OFCHECK(vfl64.size() == 3); + OFCHECK(vfl64[0] == 4.0); + OFCHECK(vfl64[1] == 5.0); + OFCHECK(vfl64[2] == 6.0); + OFCHECK(fg.getReconstructionTargetCenterPatient(val, -1).good()); + OFCHECK(val == "4\\5\\6"); +} + +OFTEST(dcmfg_ct_position) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGCTPosition fg; + OFCHECK(fg.setTablePosition(1.0).good()); + OFVector vfl64; + vfl64.push_back(1.0); + vfl64.push_back(2.0); + vfl64.push_back(3.0); + OFCHECK(fg.setDataCollectionCenterPatient(vfl64).good()); + vfl64.clear(); + vfl64.push_back(4.0); + vfl64.push_back(5.0); + vfl64.push_back(6.0); + OFCHECK(fg.setReconstructionTargetCenterPatient(vfl64).good()); + + // Check data structure in memory + check_ct_position_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); /**/ + + // Test read method: Read from dataset, write again, and compare another time + FGCTPosition fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + OFCHECK(fg.setTablePosition(100.0).good()); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGCTPosition* clone = OFstatic_cast(FGCTPosition*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} diff --git a/dcmfg/tests/t_ct_table_dynamics.cc b/dcmfg/tests/t_ct_table_dynamics.cc new file mode 100644 index 00000000..f4d9a2e2 --- /dev/null +++ b/dcmfg/tests/t_ct_table_dynamics.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for CT Table Dynamics FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fgcttabledynamics.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += "(0018,9308) SQ (Sequence with explicit length #=2) # 0, 1 CTTableDynamicsSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + fg_dump += " (0018,9309) FD 1 # 8, 1 TableSpeed\n"; + fg_dump += " (0018,9310) FD 2 # 8, 1 TableFeedPerRotation\n"; + fg_dump += " (0018,9311) FD 3 # 8, 1 SpiralPitchFactor\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + fg_dump += " (0018,9309) FD 4 # 8, 1 TableSpeed\n"; + fg_dump += " (0018,9310) FD 5 # 8, 1 TableFeedPerRotation\n"; + fg_dump += " (0018,9311) FD 6 # 8, 1 SpiralPitchFactor\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_ct_table_dynamics_fg(FGCTTableDynamics& fg) +{ + OFCondition result; + OFString val; + Float64 fl64; + OFVector::iterator item = fg.getCTTableDynamicsItems().begin(); + OFCHECK((*item)->getTableSpeed(fl64).good()); + OFCHECK(fl64 == 1.0); + OFCHECK((*item)->getTableSpeed(val).good()); + OFCHECK(val == "1"); + OFCHECK((*item)->getTableFeedPerRotation(fl64).good()); + OFCHECK(fl64 == 2.0); + OFCHECK((*item)->getTableFeedPerRotation(val).good()); + OFCHECK(val == "2"); + OFCHECK((*item)->getSpiralPitchFactor(fl64).good()); + OFCHECK(fl64 == 3.0); + OFCHECK((*item)->getSpiralPitchFactor(val).good()); + OFCHECK(val == "3"); + + item++; + OFCHECK((*item)->getTableSpeed(fl64).good()); + OFCHECK(fl64 == 4.0); + OFCHECK((*item)->getTableSpeed(val).good()); + OFCHECK(val == "4"); + OFCHECK((*item)->getTableFeedPerRotation(fl64).good()); + OFCHECK(fl64 == 5.0); + OFCHECK((*item)->getTableFeedPerRotation(val).good()); + OFCHECK(val == "5"); + OFCHECK((*item)->getSpiralPitchFactor(fl64).good()); + OFCHECK(fl64 == 6.0); + OFCHECK((*item)->getSpiralPitchFactor(val).good()); + OFCHECK(val == "6"); +} + +OFTEST(dcmfg_ct_table_dynamics) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGCTTableDynamics fg; + FGCTTableDynamics::FGCTTableDynamicsItem* fgi1 = new FGCTTableDynamics::FGCTTableDynamicsItem; + OFCHECK(fgi1->setTableSpeed(1.0).good()); + OFCHECK(fgi1->setTableFeedPerRotation(2.0).good()); + OFCHECK(fgi1->setSpiralPitchFactor(3.0).good()); + FGCTTableDynamics::FGCTTableDynamicsItem* fgi2 = new FGCTTableDynamics::FGCTTableDynamicsItem; + OFCHECK(fgi2->setTableSpeed(4.0).good()); + OFCHECK(fgi2->setTableFeedPerRotation(5.0).good()); + OFCHECK(fgi2->setSpiralPitchFactor(6.0).good()); + fg.getCTTableDynamicsItems().push_back(fgi1); + fg.getCTTableDynamicsItems().push_back(fgi2); + + // Check data structure in memory + check_ct_table_dynamics_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); /**/ + + // Test read method: Read from dataset, write again, and compare another time + FGCTTableDynamics fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + OFCHECK(fgi2->setTableSpeed(100.0).good()); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGCTTableDynamics* clone = OFstatic_cast(FGCTTableDynamics*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} diff --git a/dcmfg/tests/t_deriv_image.cc b/dcmfg/tests/t_deriv_image.cc index f3147502..a3384c12 100644 --- a/dcmfg/tests/t_deriv_image.cc +++ b/dcmfg/tests/t_deriv_image.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -63,10 +63,12 @@ static void check_deriv_image_fg(FGDerivationImage& fg) { OFVector deriv_img_items = fg.getDerivationImageItems(); OFCHECK(deriv_img_items.size() == 1); - if (deriv_img_items.size() == 0) return; + if (deriv_img_items.size() == 0) + return; OFVector& deriv_code_items = deriv_img_items[0]->getDerivationCodeItems(); OFCHECK(deriv_code_items.size() == 1); - if (deriv_code_items.size() == 0) return; + if (deriv_code_items.size() == 0) + return; CodeSequenceMacro* code_item = deriv_code_items[0]; OFString str; code_item->getCodeValue(str); @@ -103,6 +105,13 @@ static void check_deriv_image_fg(FGDerivationImage& fg) OFTEST(dcmfg_derivation_image) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + OFString fg_dump; init_template(fg_dump); @@ -112,11 +121,13 @@ OFTEST(dcmfg_derivation_image) OFCondition result = fg.addDerivationImageItem(deriv_code, "Some Description", deriv_item); OFCHECK(result.good()); OFCHECK(deriv_item != NULL); - if (result.bad() || !deriv_item) return; + if (result.bad() || !deriv_item) + return; SourceImageItem* src_image_item = new SourceImageItem(); OFCHECK(src_image_item != NULL); - if (!deriv_item) return; + if (!deriv_item) + return; OFCHECK(src_image_item->getImageSOPInstanceReference().addReferencedFrameNumber(1).good()); OFCHECK(src_image_item->getImageSOPInstanceReference().addReferencedFrameNumber(2).good()); OFCHECK(src_image_item->getImageSOPInstanceReference().addReferencedSegmentNumber(3).good()); @@ -146,7 +157,8 @@ OFTEST(dcmfg_derivation_image) dest_item.clear(); result = fg_for_read.write(dest_item); OFCHECK(result.good()); - if (result.bad()) return; + if (result.bad()) + return; dest_item.print(out); OFCHECK(out.str() == fg_dump.c_str()); @@ -158,7 +170,8 @@ OFTEST(dcmfg_derivation_image) // Test clone() method FGDerivationImage* clone = OFstatic_cast(FGDerivationImage*, fg.clone()); OFCHECK(clone != NULL); - if (clone == NULL) return; + if (clone == NULL) + return; OFCHECK(clone->compare(fg) == 0); delete clone; } diff --git a/dcmfg/tests/t_frame_content.cc b/dcmfg/tests/t_frame_content.cc index ebd87093..4a92feec 100644 --- a/dcmfg/tests/t_frame_content.cc +++ b/dcmfg/tests/t_frame_content.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019, OFFIS e.V. + * Copyright (C) 2019-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -84,6 +84,13 @@ static void check_frame_content_fg(FGFrameContent& fg) OFTEST(dcmfg_frame_content) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + OFString fg_dump; init_template(fg_dump); @@ -119,7 +126,8 @@ OFTEST(dcmfg_frame_content) dest_item.clear(); result = fg_for_read.write(dest_item); OFCHECK(result.good()); - if (result.bad()) return; + if (result.bad()) + return; dest_item.print(out); OFCHECK(out.str() == fg_dump.c_str()); @@ -131,7 +139,8 @@ OFTEST(dcmfg_frame_content) // Test clone() method FGFrameContent* clone = OFstatic_cast(FGFrameContent*, fg.clone()); OFCHECK(clone != NULL); - if (clone == NULL) return; + if (clone == NULL) + return; OFCHECK(clone->compare(fg) == 0); delete clone; } diff --git a/dcmfg/tests/t_irradiation_event_identification.cc b/dcmfg/tests/t_irradiation_event_identification.cc new file mode 100644 index 00000000..54df4de8 --- /dev/null +++ b/dcmfg/tests/t_irradiation_event_identification.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Tests for Irradiation Event Identification FG class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/dcmfg/fgirradiationeventid.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/oftest.h" + +static void init_template(OFString& fg_dump) +{ + fg_dump += "(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump + += "(0018,9477) SQ (Sequence with explicit length #=1) # 0, 1 IrradiationEventIdentificationSequence\n"; + fg_dump += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + fg_dump += " (0008,3010) UI [1.2.3.4] # 8, 1 IrradiationEventUID\n"; + fg_dump += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + fg_dump += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + fg_dump += "(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; +} + +static void check_irradiation_event_identification_fg(FGIrradiationEventIdentification& fg) +{ + OFCondition result; + OFString val; + OFCHECK(fg.getIrradiationEventUID(val).good()); + OFCHECK(val == "1.2.3.4"); +} + +OFTEST(dcmfg_irradiation_event_identification) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFString fg_dump; + init_template(fg_dump); + + FGIrradiationEventIdentification fg; + OFCHECK(fg.setIrradiationEventUID("1.2.3.4").good()); + + // Check data structure in memory + check_irradiation_event_identification_fg(fg); + + // Write to DcmItem and compare with pre-defined template + DcmItem dest_item; + OFCondition result = fg.write(dest_item); + OFCHECK(result.good()); + OFStringStream out; + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); /**/ + + // Test read method: Read from dataset, write again, and compare another time + FGIrradiationEventIdentification fg_for_read; + out.str(""); // set to empty + fg_for_read.read(dest_item); + dest_item.clear(); + result = fg_for_read.write(dest_item); + OFCHECK(result.good()); + dest_item.print(out); + OFCHECK(out.str() == fg_dump.c_str()); + + // Test compare() method + OFCHECK(fg.compare(fg_for_read) == 0); + fg_for_read.setIrradiationEventUID("5.6.7.8"); + OFCHECK(fg.compare(fg_for_read) != 0); + + // Test clone() method + FGIrradiationEventIdentification* clone = OFstatic_cast(FGIrradiationEventIdentification*, fg.clone()); + OFCHECK(clone != NULL); + OFCHECK(clone->compare(fg) == 0); + delete clone; +} diff --git a/dcmfg/tests/tests.cc b/dcmfg/tests/tests.cc index af66e545..30ac798c 100644 --- a/dcmfg/tests/tests.cc +++ b/dcmfg/tests/tests.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, OFFIS e.V. + * Copyright (C) 2015-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -20,8 +20,20 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/ofstd/oftest.h" +OFTEST_REGISTER(dcmfg_concatenation_creator); +OFTEST_REGISTER(dcmfg_concatenation_creator_fail); +OFTEST_REGISTER(dcmfg_concatenation_loader); + +OFTEST_REGISTER(dcmfg_ct_image_frame_type); +OFTEST_REGISTER(dcmfg_ct_acquisition_type); +OFTEST_REGISTER(dcmfg_ct_acquisition_details); +OFTEST_REGISTER(dcmfg_ct_table_dynamics); +OFTEST_REGISTER(dcmfg_ct_position); OFTEST_REGISTER(dcmfg_derivation_image); OFTEST_REGISTER(dcmfg_frame_content); +OFTEST_REGISTER(dcmfg_irradiation_event_identification); + OFTEST_MAIN("dcmfg") diff --git a/dcmimage/apps/dcm2pnm.cc b/dcmimage/apps/dcm2pnm.cc index 4fa8482c..b694e590 100644 --- a/dcmimage/apps/dcm2pnm.cc +++ b/dcmimage/apps/dcm2pnm.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2018, OFFIS e.V. + * Copyright (C) 1996-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -132,7 +132,7 @@ int main(int argc, char *argv[]) OFCmdUnsignedInt opt_frameCount = 1; /* default: one frame */ OFBool opt_useFrameNumber = OFFalse; /* default: use frame counter */ OFBool opt_multiFrame = OFFalse; /* default: no multiframes */ - int opt_convertToGrayscale = 0; /* default: color or grayscale */ + int opt_convertToGrayscale = 0; /* default: no conversion */ int opt_changePolarity = 0; /* default: normal polarity */ int opt_useAspectRatio = 1; /* default: use aspect ratio for scaling */ OFCmdUnsignedInt opt_useInterpolation = 1; /* default: use interpolation method '1' for scaling */ @@ -233,7 +233,7 @@ int main(int argc, char *argv[]) cmd.addSubGroup("frame selection:"); cmd.addOption("--frame", "+F", 1, "[n]umber: integer", - "select specified frame (default: 1)"); + "select specified frame (default: 1)"); cmd.addOption("--frame-range", "+Fr", 2, "[n]umber [c]ount: integer", "select c frames beginning with frame n"); cmd.addOption("--all-frames", "+Fa", "select all frames"); @@ -249,7 +249,7 @@ int main(int argc, char *argv[]) cmd.addOption("--flip-both-axes", "+Lhv", "flip image horizontally and vertically"); cmd.addSubGroup("scaling:"); - cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio (default)"); + cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio when scaling (def.)"); cmd.addOption("--ignore-aspect", "-a", "ignore pixel aspect ratio when scaling"); cmd.addOption("--interpolate", "+i", 1, "[n]umber of algorithm: integer", "use interpolation when scaling (1..4, def: 1)"); @@ -371,7 +371,7 @@ int main(int argc, char *argv[]) #endif cmd.addSubGroup("other transformations:"); - cmd.addOption("--grayscale", "+G", "convert to grayscale if necessary"); + cmd.addOption("--grayscale", "+G", "convert color image to grayscale (monochrome)"); cmd.addOption("--change-polarity", "+P", "change polarity (invert pixel output)"); cmd.addOption("--clip-region", "+C", 4, "[l]eft [t]op [w]idth [h]eight: integer", "clip image region (l, t, w, h)"); @@ -1101,7 +1101,7 @@ int main(int argc, char *argv[]) return 1; } - /* convert to grayscale if necessary */ + /* convert to grayscale if image is not monochrome */ if ((opt_convertToGrayscale) && (!di->isMonochrome())) { OFLOG_INFO(dcm2pnmLogger, "converting image to grayscale"); diff --git a/dcmimage/apps/dcmquant.cc b/dcmimage/apps/dcmquant.cc index 6cd1d31a..557a62e1 100644 --- a/dcmimage/apps/dcmquant.cc +++ b/dcmimage/apps/dcmquant.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2018, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) OFCommandLine cmd; E_FileReadMode opt_readMode = ERM_autoDetect; - E_FileWriteMode opt_writeMode = EWM_fileformat; + E_FileWriteMode opt_writeMode = EWM_createNewMeta; E_TransferSyntax opt_ixfer = EXS_Unknown; E_TransferSyntax opt_oxfer = EXS_Unknown; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; @@ -328,7 +328,7 @@ int main(int argc, char *argv[]) cmd.endOptionBlock(); cmd.beginOptionBlock(); - if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-file")) opt_writeMode = EWM_createNewMeta; if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; cmd.endOptionBlock(); @@ -486,7 +486,7 @@ int main(int argc, char *argv[]) OFLOG_INFO(dcmquantLogger, "write converted DICOM file"); // update file meta information with new SOP Instance UID - if ((opt_uidcreation || opt_secondarycapture) && (opt_writeMode == EWM_fileformat)) + if ((opt_uidcreation || opt_secondarycapture) && (opt_writeMode == EWM_createNewMeta)) opt_writeMode = EWM_updateMeta; error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, diff --git a/dcmimage/apps/dcmscale.cc b/dcmimage/apps/dcmscale.cc index 7cadfce7..e762d6e1 100644 --- a/dcmimage/apps/dcmscale.cc +++ b/dcmimage/apps/dcmscale.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2018, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) OFBool opt_uidCreation = OFTrue; E_FileReadMode opt_readMode = ERM_autoDetect; - E_FileWriteMode opt_writeMode = EWM_fileformat; + E_FileWriteMode opt_writeMode = EWM_createNewMeta; E_TransferSyntax opt_ixfer = EXS_Unknown; E_TransferSyntax opt_oxfer = EXS_Unknown; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; @@ -140,7 +140,7 @@ int main(int argc, char *argv[]) cmd.addOption("--conv-never", "+cn", "never convert color space"); #endif cmd.addSubGroup("scaling:"); - cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio (default)"); + cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio when scaling (def)"); cmd.addOption("--ignore-aspect", "-a", "ignore pixel aspect ratio when scaling"); cmd.addOption("--interpolate", "+i", 1, "[n]umber of algorithm: integer", "use interpolation when scaling (1..4, def: 1)"); @@ -330,7 +330,7 @@ int main(int argc, char *argv[]) /* output options */ cmd.beginOptionBlock(); - if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-file")) opt_writeMode = EWM_createNewMeta; if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; cmd.endOptionBlock(); @@ -567,7 +567,7 @@ int main(int argc, char *argv[]) if (!derivationDescription.empty()) { const char *oldDerivation = NULL; - if (dataset->findAndGetString(DCM_DerivationDescription, oldDerivation).good()) + if (dataset->findAndGetString(DCM_DerivationDescription, oldDerivation).good() && oldDerivation) { // append old Derivation Description, if any derivationDescription += " ["; @@ -618,9 +618,6 @@ int main(int argc, char *argv[]) // create new SOP instance UID char new_uid[100]; dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(new_uid)); - // force meta-header to refresh SOP Instance UID - if (opt_writeMode == EWM_fileformat) - opt_writeMode = EWM_updateMeta; } // ====================================================================== diff --git a/dcmimage/docs/dcm2pnm.man b/dcmimage/docs/dcm2pnm.man index cbd48576..25e22079 100644 --- a/dcmimage/docs/dcm2pnm.man +++ b/dcmimage/docs/dcm2pnm.man @@ -128,7 +128,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -329,7 +329,7 @@ PNG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -497,6 +497,6 @@ It is an error if no data dictionary can be loaded. \section dcm2pnm_copyright COPYRIGHT -Copyright (C) 1998-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1998-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmimage/docs/dcmscale.man b/dcmimage/docs/dcmscale.man index bec7e6da..bfad04d3 100644 --- a/dcmimage/docs/dcmscale.man +++ b/dcmimage/docs/dcmscale.man @@ -92,7 +92,7 @@ input transfer syntax: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -266,6 +266,6 @@ It is an error if no data dictionary can be loaded. \section dcmscale_copyright COPYRIGHT -Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2002-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmimage/include/dcmtk/dcmimage/diqthash.h b/dcmimage/include/dcmtk/dcmimage/diqthash.h index 715ee833..89a965a3 100644 --- a/dcmimage/include/dcmtk/dcmimage/diqthash.h +++ b/dcmimage/include/dcmtk/dcmimage/diqthash.h @@ -69,7 +69,7 @@ public: /** adds all pixels of all frames of the given image (which must be a * color image) to the hash table. The counter (integer value associated - * to each color) counts the occurence of the color in the image. + * to each color) counts the occurrence of the color in the image. * If more than maxcolors colors are found, the function returns zero. * @param image image in which colors are to be counted * @param newmaxval maximum pixel value to which the contents of the diff --git a/dcmimage/libsrc/dipitiff.cc b/dcmimage/libsrc/dipitiff.cc index 066e0a9e..2bec9944 100644 --- a/dcmimage/libsrc/dipitiff.cc +++ b/dcmimage/libsrc/dipitiff.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2010, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,7 @@ #include "dcmtk/dcmdata/dctypes.h" #include "dcmtk/dcmimgle/diimage.h" #include "dcmtk/dcmimage/dipitiff.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version */ BEGIN_EXTERN_C #include @@ -145,7 +146,8 @@ int DiTIFFPlugin::write( TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "unnamed"); - TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "converted DICOM image"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Converted DICOM Image"); + TIFFSetField(tif, TIFFTAG_SOFTWARE, "OFFIS DCMTK " OFFIS_DCMTK_VERSION); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, opt_rowsperstrip); /* TIFFSetField(tif, TIFFTAG_STRIPBYTECOUNTS, rows / opt_rowsperstrip); */ diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h b/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h index e5d11b78..9c49925b 100644 --- a/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2018, OFFIS e.V. + * Copyright (C) 1996-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -350,7 +350,8 @@ class DiMonoOutputPixelTemplate DCMIMGLE_DEBUG("applying VOI transformation with LUT (" << vlut->getCount() << " entries)"); const DiDisplayLUT *dlut = NULL; const double minvalue = vlut->getMinValue(); - const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; + const double lowvalue = OFstatic_cast(double, low); + const double outrange = OFstatic_cast(double, high) - lowvalue + 1; unsigned long i; if (minvalue == vlut->getMaxValue()) // LUT has only one entry or all entries are equal { @@ -369,7 +370,7 @@ class DiMonoOutputPixelTemplate value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getValue(value2)))); } else { // don't use display: invalid or absent DCMIMGLE_TRACE("monochrome rendering: VOI LUT #2"); - value = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * outrange / OFstatic_cast(double, plut->getAbsMaxRange())); + value = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * outrange / OFstatic_cast(double, plut->getAbsMaxRange())); } } else { // has no presentation LUT createDisplayLUT(dlut, disp, vlut->getBits()); @@ -382,7 +383,7 @@ class DiMonoOutputPixelTemplate value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, minvalue))); } else { // don't use display: invalid or absent DCMIMGLE_TRACE("monochrome rendering: VOI LUT #4"); - value = OFstatic_cast(T3, OFstatic_cast(double, low) + (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * outrange); + value = OFstatic_cast(T3, lowvalue + (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * outrange); } } OFBitmanipTemplate::setMem(Data, value, Count); // set output pixels to LUT value @@ -449,7 +450,7 @@ class DiMonoOutputPixelTemplate value2 = lastvalue; else value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient2); } } const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry @@ -501,15 +502,15 @@ class DiMonoOutputPixelTemplate value2 = lastvalue; else value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient2); } } } } else { // has no presentation LUT createDisplayLUT(dlut, disp, vlut->getBits()); const double gradient = outrange / OFstatic_cast(double, vlut->getAbsMaxRange()); - const T3 firstvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getFirstValue()) * gradient); - const T3 lastvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getLastValue()) * gradient); + const T3 firstvalue = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, vlut->getFirstValue()) * gradient); + const T3 lastvalue = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, vlut->getLastValue()) * gradient); if (initOptimizationLUT(lut, ocnt)) { // use LUT for optimization q = lut; @@ -549,7 +550,7 @@ class DiMonoOutputPixelTemplate else if (value >= lastentry) *(q++) = lastvalue; else - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, vlut->getValue(value)) * gradient); } } const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry @@ -595,7 +596,7 @@ class DiMonoOutputPixelTemplate else if (value >= lastentry) *(q++) = lastvalue; else - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, vlut->getValue(value)) * gradient); } } } @@ -636,7 +637,8 @@ class DiMonoOutputPixelTemplate DCMIMGLE_DEBUG("applying no VOI transformation (linear scaling)"); const double absmin = inter->getAbsMinimum(); const double absmax = inter->getAbsMaximum(); - const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; // output range + const double lowvalue = OFstatic_cast(double, low); + const double outrange = OFstatic_cast(double, high) - lowvalue + 1; // output range const unsigned long ocnt = determineOptimizationCount(inter->getAbsMaxRange()); // number of LUT entries DCMIMGLE_TRACE("intermediate pixel data - absmin: " << absmin << ", absmax: " << absmax); const T1 *p = pixel + start; @@ -676,7 +678,7 @@ class DiMonoOutputPixelTemplate for (i = 0; i < ocnt; ++i) { value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value)) * gradient2); } } const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry @@ -709,7 +711,7 @@ class DiMonoOutputPixelTemplate for (i = Count; i != 0; --i) { value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value)) * gradient2); } } } @@ -733,7 +735,7 @@ class DiMonoOutputPixelTemplate } else { // don't use display: invalid or absent DCMIMGLE_TRACE("monochrome rendering: VOI NONE #6"); for (i = 0; i < ocnt; ++i) // calculating LUT entries - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, i) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, i) * gradient); } const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry q = Data; @@ -756,7 +758,7 @@ class DiMonoOutputPixelTemplate } else { // don't use display: invalid or absent DCMIMGLE_TRACE("monochrome rendering: VOI NONE #8"); for (i = Count; i != 0; --i) - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + (OFstatic_cast(double, *(p++)) - absmin) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + (OFstatic_cast(double, *(p++)) - absmin) * gradient); } } } @@ -798,7 +800,8 @@ class DiMonoOutputPixelTemplate DCMIMGLE_DEBUG("applying sigmoid VOI transformation with window center = " << center << ", width = " << width); const DiDisplayLUT *dlut = NULL; const double absmin = inter->getAbsMinimum(); - const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range + const double lowvalue = OFstatic_cast(double, low); + const double outrange = OFstatic_cast(double, high) - lowvalue; // output range const unsigned long ocnt = determineOptimizationCount(inter->getAbsMaxRange()); // number of LUT entries const T1 *p = pixel + start; T3 *q = Data; @@ -834,7 +837,7 @@ class DiMonoOutputPixelTemplate { value = OFstatic_cast(double, i) + absmin; value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient); } } const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry @@ -863,7 +866,7 @@ class DiMonoOutputPixelTemplate { value = OFstatic_cast(double, *(p++)); value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient); } } } @@ -888,7 +891,7 @@ class DiMonoOutputPixelTemplate for (i = 0; i < ocnt; ++i) // calculating LUT entries { value = OFstatic_cast(double, i) + absmin; - *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width)) + lowvalue); } } const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry @@ -914,7 +917,7 @@ class DiMonoOutputPixelTemplate for (i = Count; i != 0; --i) { value = OFstatic_cast(double, *(p++)); - *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width)) + lowvalue); } } } @@ -960,7 +963,8 @@ class DiMonoOutputPixelTemplate const double width_1 = width - 1; const double leftBorder = center - 0.5 - width_1 / 2; // window borders, according to supplement 33 const double rightBorder = center - 0.5 + width_1 / 2; - const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range + const double lowvalue = OFstatic_cast(double, low); + const double outrange = OFstatic_cast(double, high) - lowvalue; // output range const unsigned long ocnt = determineOptimizationCount(inter->getAbsMaxRange()); // number of LUT entries const T1 *p = pixel + start; T3 *q = Data; @@ -1007,7 +1011,7 @@ class DiMonoOutputPixelTemplate value2 = pcnt - 1; // last LUT index else value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient2); } } const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry @@ -1046,7 +1050,7 @@ class DiMonoOutputPixelTemplate value2 = pcnt - 1; // last LUT index else value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); - *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + *(q++) = OFstatic_cast(T3, lowvalue + OFstatic_cast(double, plut->getValue(value2)) * gradient2); } } } diff --git a/dcmimgle/include/dcmtk/dcmimgle/diovpln.h b/dcmimgle/include/dcmtk/dcmimgle/diovpln.h index dcc674ac..adeef55b 100644 --- a/dcmimgle/include/dcmtk/dcmimgle/diovpln.h +++ b/dcmimgle/include/dcmtk/dcmimgle/diovpln.h @@ -357,14 +357,16 @@ class DCMTK_DCMIMGLE_EXPORT DiOverlayPlane * Overlay plane is clipped to the area specified by the four min/max coordinates. * Memory isn't handled internally and must therefore be deleted from calling program. * - ** @param frame number of frame - * @param xmin x-coordinate of the top left hand corner - * @param ymin y-coordinate of the top left hand corner - * @param xmax x-coordinate of the bottom right hand corner - * @param ymax y-coordinate of the bottom right hand corner - * @param bits number of bits (stored) in the resulting array - * @param fore foreground color used for the plane (0x00-0xff) - * @param back transparent background color (0x00-0xff) + ** @param frame number of frame + * @param xmin x-coordinate of the top left hand corner + * @param ymin y-coordinate of the top left hand corner + * @param xmax x-coordinate of the bottom right hand corner + * @param ymax y-coordinate of the bottom right hand corner + * @param bits number of bits (stored) in the resulting array + * @param fore foreground color used for the plane (0..2^bits-1) + * @param back transparent background color (0..2^bits-1) + * @param useOrigin use overlay plane's origin for calculating the start position + * if true (default), ignore it otherwise * ** @return pointer to pixel data if successful, NULL otherwise */ @@ -375,7 +377,8 @@ class DCMTK_DCMIMGLE_EXPORT DiOverlayPlane const Uint16 ymax, const int bits, const Uint16 fore, - const Uint16 back); + const Uint16 back, + const OFBool useOrigin = OFTrue); /** create overlay plane data in (6xxx,3000) format. * (1 bit allocated and stored, foreground color is 1, background color is 0, @@ -410,11 +413,14 @@ class DCMTK_DCMIMGLE_EXPORT DiOverlayPlane /** set internal 'cursor' to a specific position * - ** @param x new x-coordinate to start from - * @param y new y-coordinate to start from + ** @param x new x-coordinate to start from + * @param y new y-coordinate to start from + * @param useOrigin use overlay plane's origin for calculating the start position + * if true (default), ignore it otherwise */ inline void setStart(const Uint16 x, - const Uint16 y); + const Uint16 y, + const OFBool useOrigin = OFTrue); protected: @@ -547,15 +553,25 @@ inline int DiOverlayPlane::getNextBit() inline void DiOverlayPlane::setStart(const Uint16 x, - const Uint16 y) + const Uint16 y, + const OFBool useOrigin) { - if (BitsAllocated == 16) - Ptr = StartPtr + OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + - OFstatic_cast(unsigned long, x - Left); - else - BitPos = StartBitPos + (OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + - OFstatic_cast(unsigned long, x - Left)) * OFstatic_cast(unsigned long, BitsAllocated); + if (useOrigin) + { + if (BitsAllocated == 16) + Ptr = StartPtr + OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x - Left); + else + BitPos = StartBitPos + (OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x - Left)) * OFstatic_cast(unsigned long, BitsAllocated); + } else { + if (BitsAllocated == 16) + Ptr = StartPtr + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x); + else + BitPos = StartBitPos + (OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x)) * OFstatic_cast(unsigned long, BitsAllocated); + } } - #endif diff --git a/dcmimgle/libsrc/diimage.cc b/dcmimgle/libsrc/diimage.cc index ee7cfc3b..5a1b19fe 100644 --- a/dcmimgle/libsrc/diimage.cc +++ b/dcmimgle/libsrc/diimage.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2018, OFFIS e.V. + * Copyright (C) 1996-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -103,8 +103,11 @@ DiImage::DiImage(const DiDocument *docu, if (Document->getValue(DCM_FrameTime, ds)) { if (ds <= 0) - DCMIMGLE_WARN("invalid value for 'FrameTime' (" << ds << ") ... ignoring"); - else + { + /* there are rare cases, where a frame time of 0 makes sense */ + if ((ds < 0) || (NumberOfFrames > 1)) + DCMIMGLE_WARN("invalid value for 'FrameTime' (" << ds << ") ... ignoring"); + } else FrameTime = ds; } FirstFrame = (docu->getFrameStart() < NumberOfFrames) ? docu->getFrameStart() : NumberOfFrames - 1; diff --git a/dcmimgle/libsrc/diovlay.cc b/dcmimgle/libsrc/diovlay.cc index fce44fe0..cf91f101 100644 --- a/dcmimgle/libsrc/diovlay.cc +++ b/dcmimgle/libsrc/diovlay.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2017, OFFIS e.V. + * Copyright (C) 1996-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -576,7 +576,7 @@ void *DiOverlay::getFullPlaneData(const unsigned long frame, { width = op->getWidth(); height = op->getHeight(); - return op->getData(frame, 0, 0, width, height, bits, fore, back); + return op->getData(frame, 0, 0, width, height, bits, fore, back, OFFalse /*useOrigin*/); } } return NULL; diff --git a/dcmimgle/libsrc/diovpln.cc b/dcmimgle/libsrc/diovpln.cc index d982f7cb..73def7f6 100644 --- a/dcmimgle/libsrc/diovpln.cc +++ b/dcmimgle/libsrc/diovpln.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2018, OFFIS e.V. + * Copyright (C) 1996-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -76,7 +76,7 @@ DiOverlayPlane::DiOverlayPlane(const DiDocument *docu, { /* determine first frame to be processed */ FirstFrame = docu->getFrameStart(); - /* specifiy overlay group number */ + /* specify overlay group number */ DcmTagKey tag(group, DCM_OverlayRows.getElement() /* dummy */); /* get descriptive data */ tag.setElement(DCM_OverlayLabel.getElement()); @@ -349,7 +349,8 @@ void *DiOverlayPlane::getData(const unsigned long frame, const Uint16 ymax, const int bits, const Uint16 fore, - const Uint16 back) + const Uint16 back, + const OFBool useOrigin) { const unsigned long count = OFstatic_cast(unsigned long, xmax - xmin) * OFstatic_cast(unsigned long, ymax - ymin); if (Valid && (count > 0)) @@ -373,7 +374,7 @@ void *DiOverlayPlane::getData(const unsigned long frame, { for (y = ymin; y < ymax; ++y) { - setStart(xmin, y); + setStart(xmin, y, useOrigin); for (x = xmin; x < xmax; ++x) { if (getNextBit()) @@ -418,7 +419,7 @@ void *DiOverlayPlane::getData(const unsigned long frame, { for (y = ymin; y < ymax; ++y) { - setStart(xmin, y); + setStart(xmin, y, useOrigin); for (x = xmin; x < xmax; ++x, ++q) { if (getNextBit()) @@ -447,7 +448,7 @@ void *DiOverlayPlane::getData(const unsigned long frame, { for (y = ymin; y < ymax; ++y) { - setStart(xmin, y); + setStart(xmin, y, useOrigin); for (x = xmin; x < xmax; ++x, ++q) { if (getNextBit()) diff --git a/dcmiod/include/dcmtk/dcmiod/cielabutil.h b/dcmiod/include/dcmtk/dcmiod/cielabutil.h index c956527a..24bc031e 100644 --- a/dcmiod/include/dcmtk/dcmiod/cielabutil.h +++ b/dcmiod/include/dcmtk/dcmiod/cielabutil.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Pascal Getreuer, Open Connections GmbH + * Copyright (C) 2016-2019, Pascal Getreuer, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,10 +23,9 @@ #define CIELABUTIL_H #include "dcmtk/config/osconfig.h" -#define INCLUDE_CMATH // for pow() function -#include "dcmtk/ofstd/ofstdinc.h" +#define INCLUDE_CMATH // for pow() function #include "dcmtk/dcmiod/ioddef.h" - +#include "dcmtk/ofstd/ofstdinc.h" /** Class supporting color space conversions from and to CIELab. In some IODs * DICOM stores CIELab color values which must often be converted to RGB for @@ -40,173 +39,169 @@ class DCMTK_DCMIOD_EXPORT IODCIELabUtil { public: - - /// D65 standard lightpoint X component for conversion from CIEXYZ to CIELab - static const double D65_WHITEPOINT_X; - /// D65 standard lightpoint Y component for conversion from CIEXYZ to CIELab - static const double D65_WHITEPOINT_Y; - /// D65 standard lightpoint Z component for conversion from CIEXYZ to CIELab - static const double D65_WHITEPOINT_Z; - - /** Convert CIELab color representation as found in DICOM to sRGB value - * representation. See DICOM part 3 for details. - * @param R Output sRGB "R" component (red) with 0 <= R <= 1 - * @param G Output sRGB "G" component (green) with 0 <= G <= 1 - * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 - * @param LDicom Input DICOM CIELab luminance component with 0 <= L <= 65535 - * @param aDicom Input DICOM CIELab "a" component (red<->green) with 0 <= a <= 65535 - * @param bDicom Input DICOM CIELab "b" component (blue<->yellow) with 0 <= a <= 65535 - */ - static void dicomLab2RGB(double& R, double& G, double& B, double LDicom, double aDicom, double bDicom); - - /** Convert sRGB color representation to CIELab color representation as found - * in DICOM. See DICOM part 3 for details. - * @param LDicom Output CIELab luminance component with 0 <= L <= 65535 as found - * in DICOM - * @param aDicom Output CIELab "a" component (red<->green) with 0 <= a <= 65535 - * as found in DICOM - * @param bDicom Output CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 - * as found in DICOM - * @param R Input sRGB "R" component (red) with 0 <= R <= 1 - * @param G Input sRGB "G" component (green) with 0 <= G <= 1 - * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 - * - */ - static void rgb2DicomLab(double& LDicom, double& aDicom, double& bDicom, double R, double G, double B); - - /** Convert CIELab color representation as found in DICOM to CIELab - * representation. See DICOM part 3 for details. - * @param L Output CIELab luminance component with 0 <= L <= 100 - * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - * @param LDicom Input CIELab luminance component with 0 <= L <= 65535 as found - * in DICOM - * @param aDicom Input CIELab "a" component (red<->green) with 0 <= a <= 65535 - * as found in DICOM - * @param bDicom Input CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 - * as found in DICOM - */ - static void dicomlab2Lab(double& L, double& a, double& b, double LDicom, double aDicom, double bDicom); - - /** Convert CIELab color representation to CIELab color representation found - * in DICOM. See DICOM part 3 for details. - * @param LDicom Output CIELab luminance component with 0 <= L <= 65535 as found - * in DICOM - * @param aDicom Output CIELab "a" component (red<->green) with 0 <= a <= 65535 - * as found in DICOM - * @param bDicom Output CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 - * as found in DICOM - * @param L Input CIELab luminance component with 0 <= L <= 100 - * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - * - */ - static void lab2DicomLab(double& LDicom, double& aDicom, double& bDicom, double L, double a, double b); - - /** Convert sRGB color representation to CIELab representation - * @param L Output CIELab luminance component with 0 <= L <= 100 - * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - * @param R Input sRGB "R" component (red) with 0 <= R <= 1 - * @param G Input sRGB "G" component (green) with 0 <= G <= 1 - * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 - */ - static void rgb2Lab(double& L, double& a, double& b, double R, double G, double B); - - /** Convert sRGB color representation to CIE XYZ representation - * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 - * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 - * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 - * @param R Input sRGB "R" component (red) with 0 <= R <= 1 - * @param G Input sRGB "G" component (green) with 0 <= G <= 1 - * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 - */ - static void rgb2Xyz(double& X, double& Y, double& Z, double R, double G, double B); - - - /** Convert CIELAB XYZ color representation to CIELab representation - * @param L Output CIELab luminance component with 0 <= L <= 100 - * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - * @param X Input CIELab XYZ "X" component with 0 <= X <= 1 - * @param Y Input CIELab XYZ "Y" component with 0 <= Y <= 1 - * @param Z Input CIELab XYZ "Z" component with 0 <= Z <= 1 - */ - static void xyz2Lab(double& L, double& a, double& b, double X, double Y, double Z); - - /** Convert CIELab color representation to sRGB representation - * @param R Output sRGB "R" component (red) with 0 <= R <= 1 - * @param G Output sRGB "G" component (green) with 0 <= G <= 1 - * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 - * @param L Input CIELab luminance component with 0 <= L <= 100 - * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - */ - static void lab2Rgb(double& R, double& G, double& B, double L, double a, double b); - - /** Convert CIELab color representation to CIE XYZ representation - * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 - * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 - * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 - * @param L Input CIELab luminance component with 0 <= L <= 100 - * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 - * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 - */ - static void lab2Xyz(double& X, double& Y, double& Z, double L, double a, double b); - - /** Convert CIE XYZ color representation to sRGB representation - * @param R Output sRGB "R" component (red) with 0 <= R <= 1 - * @param G Output sRGB "G" component (green) with 0 <= G <= 1 - * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 - * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 - * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 - * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 - */ - static void xyz2Rgb(double& R, double& G, double& B, double X, double Y, double Z); + /// D65 standard lightpoint X component for conversion from CIEXYZ to CIELab + static const double D65_WHITEPOINT_X; + /// D65 standard lightpoint Y component for conversion from CIEXYZ to CIELab + static const double D65_WHITEPOINT_Y; + /// D65 standard lightpoint Z component for conversion from CIEXYZ to CIELab + static const double D65_WHITEPOINT_Z; + + /** Convert CIELab color representation as found in DICOM to sRGB value + * representation. See DICOM part 3 for details. + * @param R Output sRGB "R" component (red) with 0 <= R <= 1 + * @param G Output sRGB "G" component (green) with 0 <= G <= 1 + * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 + * @param LDicom Input DICOM CIELab luminance component with 0 <= L <= 65535 + * @param aDicom Input DICOM CIELab "a" component (red<->green) with 0 <= a <= 65535 + * @param bDicom Input DICOM CIELab "b" component (blue<->yellow) with 0 <= a <= 65535 + */ + static void dicomLab2RGB(double& R, double& G, double& B, double LDicom, double aDicom, double bDicom); + + /** Convert sRGB color representation to CIELab color representation as found + * in DICOM. See DICOM part 3 for details. + * @param LDicom Output CIELab luminance component with 0 <= L <= 65535 as found + * in DICOM + * @param aDicom Output CIELab "a" component (red<->green) with 0 <= a <= 65535 + * as found in DICOM + * @param bDicom Output CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 + * as found in DICOM + * @param R Input sRGB "R" component (red) with 0 <= R <= 1 + * @param G Input sRGB "G" component (green) with 0 <= G <= 1 + * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 + * + */ + static void rgb2DicomLab(double& LDicom, double& aDicom, double& bDicom, double R, double G, double B); + + /** Convert CIELab color representation as found in DICOM to CIELab + * representation. See DICOM part 3 for details. + * @param L Output CIELab luminance component with 0 <= L <= 100 + * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + * @param LDicom Input CIELab luminance component with 0 <= L <= 65535 as found + * in DICOM + * @param aDicom Input CIELab "a" component (red<->green) with 0 <= a <= 65535 + * as found in DICOM + * @param bDicom Input CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 + * as found in DICOM + */ + static void dicomlab2Lab(double& L, double& a, double& b, double LDicom, double aDicom, double bDicom); + + /** Convert CIELab color representation to CIELab color representation found + * in DICOM. See DICOM part 3 for details. + * @param LDicom Output CIELab luminance component with 0 <= L <= 65535 as found + * in DICOM + * @param aDicom Output CIELab "a" component (red<->green) with 0 <= a <= 65535 + * as found in DICOM + * @param bDicom Output CIELab "b" component (blue<->yellow) with 0 <= b <= 65535 + * as found in DICOM + * @param L Input CIELab luminance component with 0 <= L <= 100 + * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + * + */ + static void lab2DicomLab(double& LDicom, double& aDicom, double& bDicom, double L, double a, double b); + + /** Convert sRGB color representation to CIELab representation + * @param L Output CIELab luminance component with 0 <= L <= 100 + * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + * @param R Input sRGB "R" component (red) with 0 <= R <= 1 + * @param G Input sRGB "G" component (green) with 0 <= G <= 1 + * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 + */ + static void rgb2Lab(double& L, double& a, double& b, double R, double G, double B); + + /** Convert sRGB color representation to CIE XYZ representation + * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 + * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 + * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 + * @param R Input sRGB "R" component (red) with 0 <= R <= 1 + * @param G Input sRGB "G" component (green) with 0 <= G <= 1 + * @param B Input sRGB "R" component (blue) with 0 <= B <= 1 + */ + static void rgb2Xyz(double& X, double& Y, double& Z, double R, double G, double B); + + /** Convert CIELAB XYZ color representation to CIELab representation + * @param L Output CIELab luminance component with 0 <= L <= 100 + * @param a Output CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Output CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + * @param X Input CIELab XYZ "X" component with 0 <= X <= 1 + * @param Y Input CIELab XYZ "Y" component with 0 <= Y <= 1 + * @param Z Input CIELab XYZ "Z" component with 0 <= Z <= 1 + */ + static void xyz2Lab(double& L, double& a, double& b, double X, double Y, double Z); + + /** Convert CIELab color representation to sRGB representation + * @param R Output sRGB "R" component (red) with 0 <= R <= 1 + * @param G Output sRGB "G" component (green) with 0 <= G <= 1 + * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 + * @param L Input CIELab luminance component with 0 <= L <= 100 + * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + */ + static void lab2Rgb(double& R, double& G, double& B, double L, double a, double b); + + /** Convert CIELab color representation to CIE XYZ representation + * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 + * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 + * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 + * @param L Input CIELab luminance component with 0 <= L <= 100 + * @param a Input CIELab "a" component (red<->green) with -127 <= a <= 128 + * @param b Input CIELab "b" component (blue<->yellow) with -127 <= b <= 128 + */ + static void lab2Xyz(double& X, double& Y, double& Z, double L, double a, double b); + + /** Convert CIE XYZ color representation to sRGB representation + * @param R Output sRGB "R" component (red) with 0 <= R <= 1 + * @param G Output sRGB "G" component (green) with 0 <= G <= 1 + * @param B Output sRGB "R" component (blue) with 0 <= B <= 1 + * @param X Output CIELab XYZ "X" component with 0 <= X <= 1 + * @param Y Output CIELab XYZ "Y" component with 0 <= Y <= 1 + * @param Z Output CIELab XYZ "Z" component with 0 <= Z <= 1 + */ + static void xyz2Rgb(double& R, double& G, double& B, double X, double Y, double Z); protected: - - /** Perform sRGB gamma correction, transforms R to R' - * @param n The value to correct - * @return The gamma-corrected value - */ - static double gammaCorrection(double n); - - /** Perform inverse sRGB gamma correction, transforms R' to R - * @param n The value to invert - * @return The gamma-inverted value - */ - static double invGammaCorrection(double n); - - /** CIE L*a*b* f function (used to convert XYZ to L*a*b*) - * @param n value to convert - * @return The converted value - */ - static double labf(double n); - - /** CIE L*a*b* inverse f function - * @param n The value to compute the inverse for - * @return The resulting inverse - */ - static double labfInv(double n); - - /** Get the minimum of two numbers - * @param a First number - * @param b Second number - * @return The minimum of a, b. a if a and b are equal. - */ - static double min2(double a, double b); - - /** Get the minimum of three numbers - * @param a First number - * @param b Second number - * @param c Third number - * @return The minimum of a, b and c. If a value occurs more than once, - * then preference order then a is preferred if possible, b - * otherwise - */ - static double min3(double a, double b, double c); - + /** Perform sRGB gamma correction, transforms R to R' + * @param n The value to correct + * @return The gamma-corrected value + */ + static double gammaCorrection(double n); + + /** Perform inverse sRGB gamma correction, transforms R' to R + * @param n The value to invert + * @return The gamma-inverted value + */ + static double invGammaCorrection(double n); + + /** CIE L*a*b* f function (used to convert XYZ to L*a*b*) + * @param n value to convert + * @return The converted value + */ + static double labf(double n); + + /** CIE L*a*b* inverse f function + * @param n The value to compute the inverse for + * @return The resulting inverse + */ + static double labfInv(double n); + + /** Get the minimum of two numbers + * @param a First number + * @param b Second number + * @return The minimum of a, b. a if a and b are equal. + */ + static double min2(double a, double b); + + /** Get the minimum of three numbers + * @param a First number + * @param b Second number + * @param c Third number + * @return The minimum of a, b and c. If a value occurs more than once, + * then preference order then a is preferred if possible, b + * otherwise + */ + static double min3(double a, double b, double c); }; #endif // CIELABUTIL_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodcommn.h b/dcmiod/include/dcmtk/dcmiod/iodcommn.h index 5b5739d5..50d8973e 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodcommn.h +++ b/dcmiod/include/dcmtk/dcmiod/iodcommn.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -24,14 +24,14 @@ #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmiod/modpatient.h" -#include "dcmtk/dcmiod/modpatientstudy.h" -#include "dcmtk/dcmiod/modgeneralstudy.h" +#include "dcmtk/dcmiod/modcommoninstanceref.h" #include "dcmtk/dcmiod/modequipment.h" -#include "dcmtk/dcmiod/modgeneralseries.h" #include "dcmtk/dcmiod/modfor.h" +#include "dcmtk/dcmiod/modgeneralseries.h" +#include "dcmtk/dcmiod/modgeneralstudy.h" +#include "dcmtk/dcmiod/modpatient.h" +#include "dcmtk/dcmiod/modpatientstudy.h" #include "dcmtk/dcmiod/modsopcommon.h" -#include "dcmtk/dcmiod/modcommoninstanceref.h" /** Interface class to those modules and data attributes are common for many * DICOM IODs. The class offers a dedicated API for getting and settings those @@ -43,228 +43,227 @@ class DCMTK_DCMIOD_EXPORT DcmIODCommon { public: - - /** Constructor - */ - DcmIODCommon(); - - /** Copy Constructor - * @param rhs The object to copy from - */ - DcmIODCommon(const DcmIODCommon& rhs); - - /** Get rules handled by this IOD - * @return The rules - */ - OFshared_ptr getRules(); - - /** Get item managed by this IOD - * @return The item - */ - OFshared_ptr getData(); - - /** Get Patient Module - * @return Reference to Patient Module - */ - IODPatientModule& getPatient(); - - /** Get Patient Study Module - * @return Reference to Patient Study Module - */ - IODPatientStudyModule& getPatientStudy(); - - /** Get General Study Module - * @return Reference to General Study Module - */ - IODGeneralStudyModule& getStudy(); - - /** Get General Equipment Module - * @return Reference to General Equipment Module - */ - IODGeneralEquipmentModule& getEquipment(); - - /** Get Series Module - * @return Reference to General Series Module - */ - IODGeneralSeriesModule& getSeries(); - - /** Get Frame of Reference Module - * @return Reference to Frame of Reference Module - */ - IODFoRModule& getFrameOfReference(); - - /** Get SOP Common Module - * @return Reference to SOP Common Module - */ - IODSOPCommonModule& getSOPCommon(); - - /** Get Common Instance Reference Module - * @return Common Instance Reference Module - */ - IODCommonInstanceReferenceModule& getCommonInstanceReference(); - - /** Destructor - */ - virtual ~DcmIODCommon(); - - /** Clear (removes) all attributes handled by the modules of this IOD. - * IOD Rules are not reset. - */ - virtual void clearData(); - - /** Create new study. - * After generating a new Study Instance UID the method createNewSeries() is - * called, i.e.\ also a new Series Instance UID and SOP instance UID are - * generated. This is a requirement of the DICOM standard. All other - * study-related attributes from the study-level modules managed by this class - * are cleared (as well as Series and Instance level attributes). - * @param clearEquipment If OFTrue (default), also the equipment information is - * cleared (General Equipment Module)) - */ - virtual void createNewStudy(const OFBool clearEquipment = OFTrue); - - /** Create a new series. - * After generating a new Series Instance UID the method - * createNewSOPInstance() is called, i.e.\ Series-related attributes managed - * by the series-level modules of this class are cleared, as well as - * instance-level data. - * @param clearFoR If OFTrue (default), also the frame of reference is - * cleared (FoR Module) - */ - virtual void createNewSeries(const OFBool clearFoR = OFTrue); - - /** Create a new SOP instance. - * Generate a new SOP Instance UID and set the Instance Creation Date/Time - * to the current date and time. - * It could be used explicitly from the calling application if a new UID - * should be created (this is the case if the Study Instance UID or Series - * Instance UID has changed as well as any other attribute on the instance - * level, e.g.\ image pixel data). Also clears other instance related data. - */ - virtual void createNewSOPInstance(); - - /** Make sure that the IOD contains a SOP Instance, Series Instance and Study - * Instance UID. They are created if empty. Invalid UIDs are corrected if - * desired. - * @param correctInvalid If OFTrue, invalid instance UIDs will be replaced - * by new ones - */ - virtual void ensureInstanceUIDs(const OFBool correctInvalid = OFFalse); - - /** Read data into this class. - * Please note that the current content is also deleted if the reading - * process fails. If the log stream is set and valid the reason for any - * error might be obtained from the error/warning output. The reading - * process will ignore missing attributes or values as possible in order - * to read as as much as possible. - * @param dataset DICOM dataset from which the document should be read - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition read(DcmItem &dataset); - - /** Import common module attributes from dataset but only read Patient, Study, - * Series and/or Frame of Reference level portions. The current content - * is not deleted before reading. If the log stream is set and valid the - * reason for any error might be obtained from the error/warning output. - * @param dataset Reference to DICOM dataset from which the document - * should be read - * @param readPatient Read Patient-level information if OFTrue - * @param readStudy Read Study-level information if OFTrue, including - * equipment module - * @param readFoR Read Frame of Reference information if OFTrue. See - * also readSeries parameter. - * @param readSeries Read Series-level information if OFTrue, always - * includes Frame of Reference, i.e.\ readFoR is - * considered to be OFTrue - * @param takeOverCharset If OFTrue (default), Specific Character Set is - * taken over from imported dataset. If it's not - * present or empty (invalid), the attribute will - * not be present in this class either. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition importHierarchy(DcmItem& dataset, - const OFBool readPatient, - const OFBool readStudy, - const OFBool readFoR = OFFalse, - const OFBool readSeries = OFFalse, - const OFBool takeOverCharset = OFTrue); - - /** CAUTION: Parameter order (readFoR and readSeries) changed compared to the - * old import() function. - * Import common module attributes from DICOM file but only read Patient, Study, - * Series and/or Frame of Reference level portions. The current content - * is not deleted before reading. If the log stream is set and valid the - * reason for any error might be obtained from the error/warning output. - * @param filename The filename to read from. - * @param readPatient Read Patient-level information if OFTrue - * @param readStudy Read Study-level information if OFTrue, including - * equipment module - * @param readFoR Read Frame of Reference information if OFTrue. See - * also readSeries parameter. - * @param readSeries Read Series-level information if OFTrue, always - * includes Frame of Reference, i.e.\ readFoR is - * considered to be OFTrue - * @param takeOverCharset If OFTrue (default), Specific Character Set is - * taken over from imported dataset. If it's not - * present or empty (invalid), the attribute will - * not be present in this class either. - * @return EC_Normal if reading was successful (i.e.\ if any information could - * be read), otherwise an error is returned - */ - virtual OFCondition importHierarchy(const OFString& filename, - const OFBool readPatient, - const OFBool readStudy, - const OFBool readFoR = OFFalse, - const OFBool readSeries = OFFalse, - const OFBool takeOverCharset = OFTrue); - - /** Write the attributes managed by this class to DICOM dataset. - * @param dataset Reference to DICOM dataset to which the current document - * should be written. The dataset is not cleared - * before writing to it. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition write(DcmItem &dataset); - + /** Constructor + */ + DcmIODCommon(); + + /** Copy Constructor + * @param rhs The object to copy from + */ + DcmIODCommon(const DcmIODCommon& rhs); + + /** Get rules handled by this IOD + * @return The rules + */ + OFshared_ptr getRules(); + + /** Get item managed by this IOD + * @return The item + */ + OFshared_ptr getData(); + + /** Get Patient Module + * @return Reference to Patient Module + */ + IODPatientModule& getPatient(); + + /** Get Patient Study Module + * @return Reference to Patient Study Module + */ + IODPatientStudyModule& getPatientStudy(); + + /** Get General Study Module + * @return Reference to General Study Module + */ + IODGeneralStudyModule& getStudy(); + + /** Get General Equipment Module + * @return Reference to General Equipment Module + */ + IODGeneralEquipmentModule& getEquipment(); + + /** Get Series Module + * @return Reference to General Series Module + */ + IODGeneralSeriesModule& getSeries(); + + /** Get Frame of Reference Module + * @return Reference to Frame of Reference Module + */ + IODFoRModule& getFrameOfReference(); + + /** Get SOP Common Module + * @return Reference to SOP Common Module + */ + IODSOPCommonModule& getSOPCommon(); + + /** Get Common Instance Reference Module + * @return Common Instance Reference Module + */ + IODCommonInstanceReferenceModule& getCommonInstanceReference(); + + /** Destructor + */ + virtual ~DcmIODCommon(); + + /** Clear (removes) all attributes handled by the modules of this IOD. + * IOD Rules are not reset. + */ + virtual void clearData(); + + /** Create new study. + * After generating a new Study Instance UID the method createNewSeries() is + * called, i.e.\ also a new Series Instance UID and SOP instance UID are + * generated. This is a requirement of the DICOM standard. All other + * study-related attributes from the study-level modules managed by this class + * are cleared (as well as Series and Instance level attributes). + * @param clearEquipment If OFTrue (default), also the equipment information is + * cleared (General Equipment Module)) + */ + virtual void createNewStudy(const OFBool clearEquipment = OFTrue); + + /** Create a new series. + * After generating a new Series Instance UID the method + * createNewSOPInstance() is called, i.e.\ Series-related attributes managed + * by the series-level modules of this class are cleared, as well as + * instance-level data. + * @param clearFoR If OFTrue (default), also the frame of reference is + * cleared (FoR Module) + */ + virtual void createNewSeries(const OFBool clearFoR = OFTrue); + + /** Create a new SOP instance. + * Generate a new SOP Instance UID and set the Instance Creation Date/Time + * to the current date and time. + * It could be used explicitly from the calling application if a new UID + * should be created (this is the case if the Study Instance UID or Series + * Instance UID has changed as well as any other attribute on the instance + * level, e.g.\ image pixel data). Also clears other instance related data. + */ + virtual void createNewSOPInstance(); + + /** Make sure that the IOD contains a SOP Instance, Series Instance and Study + * Instance UID. They are created if empty. Invalid UIDs are corrected if + * desired. + * @param correctInvalid If OFTrue, invalid instance UIDs will be replaced + * by new ones + */ + virtual void ensureInstanceUIDs(const OFBool correctInvalid = OFFalse); + + /** Read data into this class. + * Please note that the current content is also deleted if the reading + * process fails. If the log stream is set and valid the reason for any + * error might be obtained from the error/warning output. The reading + * process will ignore missing attributes or values as possible in order + * to read as as much as possible. + * @param dataset DICOM dataset from which the document should be read + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmItem& dataset); + + /** Import common module attributes from dataset but only read Patient, Study, + * Series and/or Frame of Reference level portions. The current content + * is not deleted before reading. If the log stream is set and valid the + * reason for any error might be obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @param readPatient Read Patient-level information if OFTrue + * @param readStudy Read Study-level information if OFTrue, including + * equipment module + * @param readFoR Read Frame of Reference information if OFTrue. See + * also readSeries parameter. + * @param readSeries Read Series-level information if OFTrue, always + * includes Frame of Reference, i.e.\ readFoR is + * considered to be OFTrue + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition importHierarchy(DcmItem& dataset, + const OFBool readPatient, + const OFBool readStudy, + const OFBool readFoR = OFFalse, + const OFBool readSeries = OFFalse, + const OFBool takeOverCharset = OFTrue); + + /** CAUTION: Parameter order (readFoR and readSeries) changed compared to the + * old import() function. + * Import common module attributes from DICOM file but only read Patient, Study, + * Series and/or Frame of Reference level portions. The current content + * is not deleted before reading. If the log stream is set and valid the + * reason for any error might be obtained from the error/warning output. + * @param filename The filename to read from. + * @param readPatient Read Patient-level information if OFTrue + * @param readStudy Read Study-level information if OFTrue, including + * equipment module + * @param readFoR Read Frame of Reference information if OFTrue. See + * also readSeries parameter. + * @param readSeries Read Series-level information if OFTrue, always + * includes Frame of Reference, i.e.\ readFoR is + * considered to be OFTrue + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if reading was successful (i.e.\ if any information could + * be read), otherwise an error is returned + */ + virtual OFCondition importHierarchy(const OFString& filename, + const OFBool readPatient, + const OFBool readStudy, + const OFBool readFoR = OFFalse, + const OFBool readSeries = OFFalse, + const OFBool takeOverCharset = OFTrue); + + /** Write the attributes managed by this class to DICOM dataset. + * @param dataset Reference to DICOM dataset to which the current document + * should be written. The dataset is not cleared + * before writing to it. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmItem& dataset); private: + /** Copy assignment disabled + * @param rhs Object to copy from + * @return Reference to "this" object + */ + DcmIODCommon& operator=(const DcmIODCommon& rhs); - /** Copy assignment disabled - */ - DcmIODCommon& operator=(const DcmIODCommon&); - - /// The data hold by this class (shared with modules below) - OFshared_ptr m_Item; + /// The data hold by this class (shared with modules below) + OFshared_ptr m_Item; - /// The rules hold by this class (shared with modules below) - OFshared_ptr m_Rules; + /// The rules hold by this class (shared with modules below) + OFshared_ptr m_Rules; - /// Patient Module - IODPatientModule m_Patient; + /// Patient Module + IODPatientModule m_Patient; - /// Patient Study Module - IODPatientStudyModule m_PatientStudy; + /// Patient Study Module + IODPatientStudyModule m_PatientStudy; - /// General Study Module - IODGeneralStudyModule m_Study; + /// General Study Module + IODGeneralStudyModule m_Study; - /// General Equipment Module - IODGeneralEquipmentModule m_Equipment; + /// General Equipment Module + IODGeneralEquipmentModule m_Equipment; - /// General Series Module - IODGeneralSeriesModule m_Series; + /// General Series Module + IODGeneralSeriesModule m_Series; - /// Frame of Reference Module - IODFoRModule m_FrameOfReference; + /// Frame of Reference Module + IODFoRModule m_FrameOfReference; - /// SOP Common Module - IODSOPCommonModule m_SOPCommon; + /// SOP Common Module + IODSOPCommonModule m_SOPCommon; - /// Common Instance Reference Module - IODCommonInstanceReferenceModule m_CommonInstanceReferenceModule; + /// Common Instance Reference Module + IODCommonInstanceReferenceModule m_CommonInstanceReferenceModule; - /// Collects all modules of this class for convenience (iteration) - OFVector m_Modules; + /// Collects all modules of this class for convenience (iteration) + OFVector m_Modules; }; #endif // IODCOMMN_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h b/dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h index 8646e96f..f5c09c6d 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h +++ b/dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,11 +23,11 @@ #define IODCONTENTITEMMACRO_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" /** Class representing the Content Item Macro: * @@ -50,56 +50,145 @@ class DCMTK_DCMIOD_EXPORT ContentItemMacro : public IODComponent { public: - - enum ValueType - { - // Value is empty and not provided - VT_EMPTY, - // Value is provided but not known to the implementation - VT_UNKNOWN, - VT_DATE, - VT_TIME, - VT_DATETIME, - VT_PNAME, - VT_UIDREF, - VT_TEXT, - VT_CODE, - VT_NUMERIC, - VT_COMPOSITE, - VT_IMAGE - }; - - /** Class representing an item within the Content Item Macro's Referenced - * SOP Sequence - */ - class DCMTK_DCMIOD_EXPORT ReferencedSOPSequenceItem : public IODComponent - { - public: + enum ValueType + { + // Value is empty and not provided + VT_EMPTY, + // Value is provided but not known to the implementation + VT_UNKNOWN, + VT_DATE, + VT_TIME, + VT_DATETIME, + VT_PNAME, + VT_UIDREF, + VT_TEXT, + VT_CODE, + VT_NUMERIC, + VT_COMPOSITE, + VT_IMAGE + }; + + /** Class representing an item within the Content Item Macro's Referenced + * SOP Sequence + */ + class DCMTK_DCMIOD_EXPORT ReferencedSOPSequenceItem : public IODComponent + { + public: + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + ReferencedSOPSequenceItem(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + ReferencedSOPSequenceItem(IODComponent* parent = NULL); + + /** Copy Constructor, performs deep copy + * @param rhs The parent of the IOD component (NULL if none or unknown) + */ + ReferencedSOPSequenceItem(const ReferencedSOPSequenceItem& rhs); + + /** Virtual Destructor + */ + virtual ~ReferencedSOPSequenceItem(); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the component ("ReferencedSOPSequenceItem") + */ + virtual OFString getName() const; + + /** Get SOPInstanceReferenceMacro + * @return a reference to the included SOPInstanceReferenceMacro + */ + virtual SOPInstanceReferenceMacro& getSOPInstanceReferenceMacro(); + + /** Get ReferencedFrameNumber + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedFrameNumber(OFString& value, const signed long pos = 0) const; + + /** Get ReferencedSegmentNumber + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSegmentNumber(Uint16& value, const unsigned long pos = 0) const; + + /** Set ReferencedFrameNumber + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferencedFrameNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set ReferencedSegmentNumber + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (US) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferencedSegmentNumber(const Uint16 value, const OFBool checkValue = OFTrue); + + protected: + /// The name of this item ("ReferencedSOPSequenceItem") + static const OFString m_ComponentName; + + /// SOP Instance Reference Macro + SOPInstanceReferenceMacro m_SOPInstanceReferenceMacro; + }; /** Constructor * @param item The item to be used for data storage. If NULL, the * class creates an empty data container. * @param rules The rule set for this class. If NULL, the class creates * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) */ - ReferencedSOPSequenceItem(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); + ContentItemMacro(OFshared_ptr item, OFshared_ptr rules); /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) */ - ReferencedSOPSequenceItem(IODComponent* parent = NULL); + ContentItemMacro(); - /** Copy Constructor, performs deep copy - * @param rhs The parent of the IOD component (NULL if none or unknown) + /** Destructor */ - ReferencedSOPSequenceItem(const ReferencedSOPSequenceItem& rhs); + virtual ~ContentItemMacro(); - /** Virtual Destructor + ContentItemMacro(const ContentItemMacro& rhs); + + /** Resets rules to their original values */ - virtual ~ReferencedSOPSequenceItem(); + virtual void resetRules(); + + /** Get name of module ("ContentItemMacro") + * @return Name of the module ("ContentItemMacro") + */ + virtual OFString getName() const; /** Read attributes from given item into this class * @param source The source to read from @@ -107,8 +196,7 @@ public: * old data is overwritten (or amended) * @result EC_Normal if reading was successful, error otherwise */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); /** Write attributes from this class into given item * @param destination The item to write to @@ -116,363 +204,241 @@ public: */ virtual OFCondition write(DcmItem& destination); - /** Resets rules to their original values + /** Get ValueType + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise */ - virtual void resetRules(); + virtual OFCondition getValueType(OFString& value, const signed long pos = 0) const; - /** Get name of macro - * @return Name of the component ("ReferencedSOPSequenceItem") + /** Get ValueType + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise */ - virtual OFString getName() const; + virtual OFCondition getValueType(ValueType& value) const; + + /** Get reference to the ConceptNameCodeSequence + * @return a reference to the ConceptNameCodeSequence + */ + virtual CodeSequenceMacro* getConceptNameCodeSequence(); + + /** Get a reference to the entire ConceptNameCodeSequence, including items + * exceeding the value multiplicity restriction of "1" + * @return a reference to the entire ConceptNameCodeSequence + */ + virtual OFVector& getEntireConceptNameCodeSequence(); + + /** Get DateTime + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDateTime(OFString& value, const signed long pos = 0) const; + + /** Get Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDate(OFString& value, const signed long pos = 0) const; - /** Get SOPInstanceReferenceMacro - * @return a reference to the included SOPInstanceReferenceMacro + /** Get Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTime(OFString& value, const signed long pos = 0) const; + + /** Get PersonName + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise */ - virtual SOPInstanceReferenceMacro& getSOPInstanceReferenceMacro(); + virtual OFCondition getPersonName(OFString& value, const signed long pos = 0) const; - /** Get ReferencedFrameNumber + /** Get UID * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getReferencedFrameNumber(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getUID(OFString& value, const signed long pos = 0) const; - /** Get ReferencedSegmentNumber + /** Get TextValue * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getReferencedSegmentNumber(Uint16 &value, - const signed long pos = 0) const; + virtual OFCondition getTextValue(OFString& value, const signed long pos = 0) const; - /** Set ReferencedFrameNumber + /** Get reference to the ConceptCodeSequence + * @return a reference to the ConceptCodeSequence + */ + virtual CodeSequenceMacro* getConceptCodeSequence(); + + /** Get a reference to the entire ConceptCodeSequence, including items + * exceeding the value multiplicity restriction of "1" + * @return a reference to the entire ConceptCodeSequence + */ + virtual OFVector& getEntireConceptCodeSequence(); + + /** Get NumericValue + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getNumericValue(OFString& value, const signed long pos = 0) const; + + /** Get FloatingPointValue + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloatingPointValue(Float64& value, const unsigned long pos = 0) const; + + /** Get RationalNumeratorValue + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRationalNumeratorValue(Sint32& value, const unsigned long pos = 0) const; + + /** Get RationalDenominatorValue + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRationalDenominatorValue(Uint32& value, const unsigned long pos = 0) const; + + /** Get reference to the MeasurementUnitsCodeSequence + * @return a reference to the MeasurementUnitsCodeSequence + */ + virtual CodeSequenceMacro* getMeasurementUnitsCodeSequence(); + + /** Get a reference to the entire MeasurementUnitsCodeSequence, including items + * exceeding the value multiplicity restriction of "1" + * @return a reference to the entire MeasurementUnitsCodeSequence + */ + virtual OFVector& getEntireMeasurementUnitsCodeSequence(); + + /** Get reference to the ReferencedSOPSequence + * @return a reference to the ReferencedSOPSequence + */ + virtual ReferencedSOPSequenceItem* getReferencedSOPSequence(); + + /** Get a reference to the entire ReferencedSOPSequence, including items + * exceeding the value multiplicity restriction of "1" + * @return a reference to the entire ReferencedSOPSequence + */ + virtual OFVector& getEntireReferencedSOPSequence(); + + /** Set ValueType * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1-n) if enabled + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setReferencedFrameNumber(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setValueType(const OFString& value, const OFBool checkValue = OFTrue); - /** Set ReferencedSegmentNumber + /** Set ValueType * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (US) and VM (1-n) if enabled + * @param checkValue Check 'value'. Does nothing, here for consistency with + * other set() functions. * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setReferencedSegmentNumber(const Uint16 value, - const OFBool checkValue = OFTrue); - - protected: - - /// The name of this item ("ReferencedSOPSequenceItem") - static const OFString m_ComponentName; - - /// SOP Instance Reference Macro - SOPInstanceReferenceMacro m_SOPInstanceReferenceMacro; - }; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - ContentItemMacro(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - ContentItemMacro(); - - /** Destructor - */ - virtual ~ContentItemMacro(); - - ContentItemMacro(const ContentItemMacro& rhs); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("ContentItemMacro") - * @return Name of the module ("ContentItemMacro") - */ - virtual OFString getName() const; - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Get ValueType - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getValueType(OFString &value, - const signed long pos = 0) const; - - /** Get ValueType - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getValueType(ValueType &value) const; - - /** Get reference to the ConceptNameCodeSequence - * @return a reference to the ConceptNameCodeSequence - */ - virtual CodeSequenceMacro* getConceptNameCodeSequence(); - - /** Get a reference to the entire ConceptNameCodeSequence, including items - * exceeding the value multiplicity restriction of "1" - * @return a reference to the entire ConceptNameCodeSequence - */ - virtual OFVector& getEntireConceptNameCodeSequence(); - - /** Get DateTime - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDateTime(OFString &value, - const signed long pos = 0) const; - - /** Get Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDate(OFString &value, - const signed long pos = 0) const; - - /** Get Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTime(OFString &value, - const signed long pos = 0) const; - - /** Get PersonName - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPersonName(OFString &value, - const signed long pos = 0) const; - - /** Get UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getUID(OFString &value, - const signed long pos = 0) const; - - /** Get TextValue - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTextValue(OFString &value, - const signed long pos = 0) const; - - /** Get reference to the ConceptCodeSequence - * @return a reference to the ConceptCodeSequence - */ - virtual CodeSequenceMacro* getConceptCodeSequence(); - - /** Get a reference to the entire ConceptCodeSequence, including items - * exceeding the value multiplicity restriction of "1" - * @return a reference to the entire ConceptCodeSequence - */ - virtual OFVector& getEntireConceptCodeSequence(); - - /** Get NumericValue - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getNumericValue(OFString &value, - const signed long pos = 0) const; - - /** Get FloatingPointValue - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFloatingPointValue(Float64 &value, - const signed long pos = 0) const; - - /** Get RationalNumeratorValue - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRationalNumeratorValue(Sint32 &value, - const signed long pos = 0) const; - - /** Get RationalDenominatorValue - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRationalDenominatorValue(Uint32 &value, - const signed long pos = 0) const; - - /** Get reference to the MeasurementUnitsCodeSequence - * @return a reference to the MeasurementUnitsCodeSequence - */ - virtual CodeSequenceMacro* getMeasurementUnitsCodeSequence(); - - /** Get a reference to the entire MeasurementUnitsCodeSequence, including items - * exceeding the value multiplicity restriction of "1" - * @return a reference to the entire MeasurementUnitsCodeSequence - */ - virtual OFVector& getEntireMeasurementUnitsCodeSequence(); - - /** Get reference to the ReferencedSOPSequence - * @return a reference to the ReferencedSOPSequence - */ - virtual ReferencedSOPSequenceItem* getReferencedSOPSequence(); - - /** Get a reference to the entire ReferencedSOPSequence, including items - * exceeding the value multiplicity restriction of "1" - * @return a reference to the entire ReferencedSOPSequence - */ - virtual OFVector& getEntireReferencedSOPSequence(); - - /** Set ValueType - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setValueType(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set ValueType - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Does nothing, here for consistency with - * other set() functions. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setValueType(const ValueType value, - const OFBool checkValue = OFTrue); - - /** Set DateTime - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DT) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDateTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Time - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set PersonName - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPersonName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set TextValue - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UT) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setTextValue(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set NumericValue - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setNumericValue(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set FloatingPointValue - * @param value Value to be set (single value only) or "" for no value - * @param pos Index of the value to be set (starting from 0) - * @param checkValue Check 'value' for conformance with VR (FD) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setFloatingPointValue(const Float64 value, - const unsigned long pos = 0, - const OFBool checkValue = OFTrue); - - /** Set RationalNumeratorValue - * @param value Value to be set (single value only) or "" for no value - * @param pos Index of the value to be set (starting from 0) - * @param checkValue Check 'value' for conformance with VR (SL) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRationalNumeratorValue(const Sint32 value, - const unsigned long pos = 0, - const OFBool checkValue = OFTrue); - - /** Set RationalDenominatorValue - * @param value Value to be set (single value only) or "" for no value - * @param pos Index of the value to be set (starting from 0) - * @param checkValue Check 'value' for conformance with VR (UL) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRationalDenominatorValue(const Uint32 value, - const unsigned long pos = 0, - const OFBool checkValue = OFTrue); - - virtual OFString toString(); + virtual OFCondition setValueType(const ValueType value, const OFBool checkValue = OFTrue); -protected: + /** Set DateTime + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDateTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDate(const OFString& value, const OFBool checkValue = OFTrue); - /// The name of this module ("ContentItemMacro") - static const OFString m_ModuleName; + /** Set Time + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set PersonName + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPersonName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set TextValue + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTextValue(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set NumericValue + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setNumericValue(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set FloatingPointValue + * @param value Value to be set (single value only) or "" for no value + * @param pos Index of the value to be set (starting from 0) + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setFloatingPointValue(const Float64 value, const unsigned long pos = 0, const OFBool checkValue = OFTrue); + + /** Set RationalNumeratorValue + * @param value Value to be set (single value only) or "" for no value + * @param pos Index of the value to be set (starting from 0) + * @param checkValue Check 'value' for conformance with VR (SL) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setRationalNumeratorValue(const Sint32 value, const unsigned long pos = 0, const OFBool checkValue = OFTrue); + + /** Set RationalDenominatorValue + * @param value Value to be set (single value only) or "" for no value + * @param pos Index of the value to be set (starting from 0) + * @param checkValue Check 'value' for conformance with VR (UL) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setRationalDenominatorValue(const Uint32 value, const unsigned long pos = 0, const OFBool checkValue = OFTrue); + + virtual OFString toString(); + +protected: + /// The name of this module ("ContentItemMacro") + static const OFString m_ModuleName; - /// ConceptNameCodeSequence - OFVector m_ConceptNameCodeSequence; + /// ConceptNameCodeSequence + OFVector m_ConceptNameCodeSequence; - /// ConceptCodeSequence - OFVector m_ConceptCodeSequence; + /// ConceptCodeSequence + OFVector m_ConceptCodeSequence; - /// MeasurementUnitsCodeSequence - OFVector m_MeasurementUnitsCodeSequence; + /// MeasurementUnitsCodeSequence + OFVector m_MeasurementUnitsCodeSequence; - /// ReferencedSOPSequence - OFVector m_ReferencedSOPSequence; + /// ReferencedSOPSequence + OFVector m_ReferencedSOPSequence; }; #endif // IODCONTENTITEMMACRO_H diff --git a/dcmiod/include/dcmtk/dcmiod/ioddef.h b/dcmiod/include/dcmtk/dcmiod/ioddef.h index 1989579d..167488b7 100644 --- a/dcmiod/include/dcmtk/dcmiod/ioddef.h +++ b/dcmiod/include/dcmtk/dcmiod/ioddef.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,14 +19,12 @@ * */ - #ifndef IODDEF_H #define IODDEF_H #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/ofdefine.h" - // Make sure DLL exports work for this module #ifdef dcmiod_EXPORTS @@ -35,5 +33,4 @@ #define DCMTK_DCMIOD_EXPORT DCMTK_DECL_IMPORT #endif - #endif // IODDEF_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodimage.h b/dcmiod/include/dcmtk/dcmiod/iodimage.h index 2444edd9..3328186f 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodimage.h +++ b/dcmiod/include/dcmtk/dcmiod/iodimage.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,15 +23,15 @@ #define IODIMAGE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofutil.h" -#include "dcmtk/ofstd/ofvriant.h" #include "dcmtk/dcmiod/iodcommn.h" #include "dcmtk/dcmiod/modgeneralimage.h" #include "dcmtk/dcmiod/modimagepixelvariant.h" +#include "dcmtk/ofstd/ofutil.h" +#include "dcmtk/ofstd/ofvriant.h" class IODDoubleFloatingPointImagePixelModule; class IODFloatingPointImagePixelModule; -template +template class IODImagePixelModule; /** Class for managing common image IOD attributes. At the moment support for @@ -44,269 +44,269 @@ class IODImagePixelModule; * Image Pixel Module. */ #ifdef HAVE_CXX11 -template -struct DcmIODImageHasType -: std::false_type {}; +template +struct DcmIODImageHasType : std::false_type +{ +}; -template -struct DcmIODImageHasType -: std::true_type {}; +template +struct DcmIODImageHasType : std::true_type +{ +}; -template -struct DcmIODImageHasType -: DcmIODImageHasType::type {}; +template +struct DcmIODImageHasType : DcmIODImageHasType::type +{ +}; -template +template #else -template +template #endif class DcmIODImage : public DcmIODCommon { public: + /** typedef for old compilers that do not define the type 'DcmIODImage' in + * derived classes. + */ + typedef DcmIODImage IODImage; - /** typedef for old compilers that do not define the type 'DcmIODImage' in - * derived classes. - */ - typedef DcmIODImage IODImage; - - /** A good comment would be nice, but I have nothing in mind - */ + /** A good comment would be nice, but I have nothing in mind + */ #ifdef HAVE_CXX11 - using IODImagePixelModuleType = IODImagePixelVariant; + using IODImagePixelModuleType = IODImagePixelVariant; #else - typedef IODImagePixelVariant IODImagePixelModuleType; + typedef IODImagePixelVariant IODImagePixelModuleType; #endif - /** Constructor, creates new DcmIODImage instance with integer-based pixel data. - */ - DcmIODImage() - : DcmIODCommon() - , m_GeneralImage(getData(), getRules()) - , m_ImagePixel() - { - - } - - /** Constructor, constructs new DcmIODImage instance with integer, float or - * double based Image Pixel Module (i. e. Image Pixel Module, Floating Point - * Image Pixel Module or the Double Floating Point Image Pixel Module), based - * on the provided Image Pixel module type. - */ - template - DcmIODImage(OFin_place_type_t(ImagePixel)) - : DcmIODCommon() - , m_GeneralImage(getData(), getRules()) - , m_ImagePixel(ImagePixel(getData(), getRules())) - { - - } - - /** Virtual Destructor - */ - virtual ~DcmIODImage() - { - - } - - /** Get General Image Module - * @return Reference to General Image Module - */ - IODGeneralImageModule& getGeneralImage() - { - return m_GeneralImage; - } - - /** Get Image Pixel Module (variant) - * @return Reference to Image Pixel Module - */ - IODImagePixelModuleType& getImagePixel() - { - return m_ImagePixel; - } - - /** Clear (removes) all attributes handled by the modules of this IOD. - * IOD Rules are not reset. - */ - virtual void clearData() - { - DcmIODCommon::clearData(); - m_GeneralImage.clearData(); - m_ImagePixel.clearData(); - } - - /** Read common image module attributes (all those handled by this class) - * from given item. Reads attributes from base class DcmIODCommon before. - * The current content is deleted even if the reading process fails. - * If the log stream is set and valid the reason for any error might be - * obtained from the error/warning output. - * @param dataset Reference to DICOM dataset from which the document - * should be read - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition read(DcmItem &dataset) - { - // re-initialize object - clearData(); - - // read from base classes - DcmIODCommon::read(dataset); - m_GeneralImage.read(dataset, OFTrue /* clear old data */); - - return readFloatingPointDoubleImagePixel(dataset); - } - - /** Write current common image module's attributes to DICOM dataset. Also - * writes attributes of base class DcmIODCommon afterwards. - * @param dataset Reference to DICOM dataset to which the current data - * should be written. The dataset is not cleared before writing - * to it! - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition write(DcmItem &dataset) - { - OFCondition result = EC_Normal; - - // Write base class attributes to dataset - result = DcmIODCommon::write(dataset); - - // Write extra modules to dataset - if (result.good()) - result = m_GeneralImage.write(dataset); - if (result.good()) - result = m_ImagePixel.write(dataset); - - return result; - } + /** Constructor, creates new DcmIODImage instance with integer-based pixel data. + */ + DcmIODImage() + : DcmIODCommon() + , m_GeneralImageModuleEnabled(OFTrue) + , m_GeneralImage(getData(), getRules()) + , m_ImagePixel() + { + } -private: + /** Constructor, constructs new DcmIODImage instance with integer, float or + * double based Image Pixel Module (i. e. Image Pixel Module, Floating Point + * Image Pixel Module or the Double Floating Point Image Pixel Module), based + * on the provided Image Pixel module type. + */ + template + DcmIODImage(OFin_place_type_t(ImagePixel)) + : DcmIODCommon() + , m_GeneralImageModuleEnabled(OFTrue) + , m_GeneralImage(getData(), getRules()) + , m_ImagePixel(ImagePixel(getData(), getRules())) + { + } + + /** Virtual Destructor + */ + virtual ~DcmIODImage() + { + } + + virtual void setGeneralImageModuleEnabled(const OFBool enabled) + { + m_GeneralImageModuleEnabled = enabled; + } + + virtual OFBool getGeneralImageModuleEnabled() const + { + return m_GeneralImageModuleEnabled; + } + + /** Get General Image Module + * @return Reference to General Image Module + */ + IODGeneralImageModule& getGeneralImage() + { + return m_GeneralImage; + } + + /** Get Image Pixel Module (variant) + * @return Reference to Image Pixel Module + */ + IODImagePixelModuleType& getImagePixel() + { + return m_ImagePixel; + } + + /** Clear (removes) all attributes handled by the modules of this IOD. + * IOD Rules are not reset. + */ + virtual void clearData() + { + DcmIODCommon::clearData(); + m_GeneralImage.clearData(); + m_ImagePixel.clearData(); + } + + /** Read common image module attributes (all those handled by this class) + * from given item. Reads attributes from base class DcmIODCommon before. + * The current content is deleted even if the reading process fails. + * If the log stream is set and valid the reason for any error might be + * obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmItem& dataset) + { + // re-initialize object + clearData(); + + // read from base classes + DcmIODCommon::read(dataset); + if (m_GeneralImageModuleEnabled) + { + m_GeneralImage.read(dataset, OFTrue /* clear old data */); + } + + return readFloatingPointDoubleImagePixel(dataset); + } + + /** Write current common image module's attributes to DICOM dataset. Also + * writes attributes of base class DcmIODCommon afterwards. + * @param dataset Reference to DICOM dataset to which the current data + * should be written. The dataset is not cleared before writing + * to it! + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmItem& dataset) + { + OFCondition result = EC_Normal; + + // Write base class attributes to dataset + result = DcmIODCommon::write(dataset); + + // Write extra modules to dataset + if (result.good() && m_GeneralImageModuleEnabled) + result = m_GeneralImage.write(dataset); + if (result.good()) + result = m_ImagePixel.write(dataset); + + return result; + } - template +private: + template #ifdef HAVE_CXX11 - typename std::enable_if::value,OFCondition>::type + typename std::enable_if::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type::value != -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type::value != -1), OFCondition>::type #endif - readFloatingPointDoubleImagePixel(DcmItem& dataset) - { - if (dataset.tagExists(DCM_DoubleFloatPixelData)) - return OFget(&(m_ImagePixel = T(getData(),getRules())))->read(dataset); - return readFloatingPointImagePixel(dataset); - } - - template + readFloatingPointDoubleImagePixel(DcmItem& dataset) + { + if (dataset.tagExists(DCM_DoubleFloatPixelData)) + return OFget(&(m_ImagePixel = T(getData(), getRules())))->read(dataset); + return readFloatingPointImagePixel(dataset); + } + + template #ifdef HAVE_CXX11 - typename std::enable_if::value,OFCondition>::type + typename std::enable_if::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type::value == -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type::value == -1), OFCondition>::type #endif - readFloatingPointDoubleImagePixel(DcmItem& dataset) - { - return readFloatingPointImagePixel(dataset); - } + readFloatingPointDoubleImagePixel(DcmItem& dataset) + { + return readFloatingPointImagePixel(dataset); + } - template + template #ifdef HAVE_CXX11 - typename std::enable_if::value,OFCondition>::type + typename std::enable_if::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type::value != -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type::value != -1), OFCondition>::type #endif - readFloatingPointImagePixel(DcmItem& dataset) - { - if (dataset.tagExists(DCM_FloatPixelData)) - return OFget(&(m_ImagePixel = T(getData(),getRules())))->read(dataset); - return readIntegerImagePixel(dataset); - } - - template + readFloatingPointImagePixel(DcmItem& dataset) + { + if (dataset.tagExists(DCM_FloatPixelData)) + return OFget(&(m_ImagePixel = T(getData(), getRules())))->read(dataset); + return readIntegerImagePixel(dataset); + } + + template #ifdef HAVE_CXX11 - typename std::enable_if::value,OFCondition>::type + typename std::enable_if::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type::value == -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type::value == -1), OFCondition>::type #endif - readFloatingPointImagePixel(DcmItem& dataset) - { - return readIntegerImagePixel(dataset); - } - - OFCondition readIntegerImagePixel(DcmItem& dataset) - { - Uint16 allocated, representation; - if - ( - dataset.tagExists(DCM_PixelData) && - dataset.findAndGetUint16(DCM_BitsAllocated, allocated).good() && - dataset.findAndGetUint16(DCM_PixelRepresentation, representation).good() - ) - switch ((allocated > 8 ? 2 : 0) | (representation ? 1 : 0)) + readFloatingPointImagePixel(DcmItem& dataset) + { + return readIntegerImagePixel(dataset); + } + + OFCondition readIntegerImagePixel(DcmItem& dataset) { - case 0: - return readImagePixel(dataset); - case 1: - return readImagePixel(dataset); - case 2: - return readImagePixel(dataset); - case 3: - return readImagePixel(dataset); - default: - break; + Uint16 allocated, representation; + // Pixel data is not managed right now by Image Pixel Module class. + if (/* dataset.tagExists(DCM_PixelData) && */ dataset.findAndGetUint16(DCM_BitsAllocated, allocated).good() + && dataset.findAndGetUint16(DCM_PixelRepresentation, representation).good()) + switch ((allocated > 8 ? 2 : 0) | (representation ? 1 : 0)) + { + case 0: + return readImagePixel(dataset); + case 1: + return readImagePixel(dataset); + case 2: + return readImagePixel(dataset); + case 3: + return readImagePixel(dataset); + default: + break; + } + return IOD_EC_InvalidPixelData; } - return IOD_EC_InvalidPixelData; - } - template + template #ifdef HAVE_CXX11 - typename std::enable_if,Types...>::value,OFCondition>::type + typename std::enable_if, Types...>::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type,OFVARIADIC_TEMPLATE_PARAMETER_PACK(T)>::value != -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type, OFVARIADIC_TEMPLATE_PARAMETER_PACK(T)>::value != -1), + OFCondition>::type #endif - readImagePixel(DcmItem& dataset) - { - return OFget >(&(m_ImagePixel = IODImagePixelModule(getData(),getRules())))->read(dataset); - } + readImagePixel(DcmItem& dataset) + { + return OFget >(&(m_ImagePixel = IODImagePixelModule(getData(), getRules()))) + ->read(dataset); + } - template + template #ifdef HAVE_CXX11 - typename std::enable_if,Types...>::value,OFCondition>::type + typename std::enable_if, Types...>::value, OFCondition>::type #else - OFTypename OFenable_if - < - (OFvariadic_find_type,OFVARIADIC_TEMPLATE_PARAMETER_PACK(T)>::value == -1), - OFCondition - >::type + OFTypename + OFenable_if<(OFvariadic_find_type, OFVARIADIC_TEMPLATE_PARAMETER_PACK(T)>::value == -1), + OFCondition>::type #endif - readImagePixel(DcmItem& dataset) - { - // Avoid compiler warning about unused parameter - OFstatic_cast(void, dataset); - return IOD_EC_InvalidPixelData; - } - - /// General Image Module - IODGeneralImageModule m_GeneralImage; - - /// Image Pixel Module - IODImagePixelModuleType m_ImagePixel; + readImagePixel(DcmItem& dataset) + { + // Avoid compiler warning about unused parameter + OFstatic_cast(void, dataset); + return IOD_EC_InvalidPixelData; + } + + /// Denotes whether General Image Module is used in this class (OFTrue) or not (OFFalse). + /// This switch can be configured using a call to setGeneralImageModuleEnabled(). The + /// default is OFTrue. + OFBool m_GeneralImageModuleEnabled; + + /// General Image Module + IODGeneralImageModule m_GeneralImage; + + /// Image Pixel Module + IODImagePixelModuleType m_ImagePixel; }; #endif // IODIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodmacro.h b/dcmiod/include/dcmtk/dcmiod/iodmacro.h index 4430c2cd..bfa29184 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodmacro.h +++ b/dcmiod/include/dcmtk/dcmiod/iodmacro.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,11 +23,11 @@ #define IODMACRO_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/ofstd/ofstring.h" -#include "dcmtk/dcmdata/dctk.h" // For VR classes, i.e. DcmCodeString etc. +#include "dcmtk/dcmdata/dctk.h" // For VR classes, i.e. DcmCodeString etc. #include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing a Code Sequence Macro */ @@ -35,166 +35,220 @@ class DCMTK_DCMIOD_EXPORT CodeSequenceMacro : public IODComponent { public: + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(IODComponent* parent = NULL); + + /** Copy Constructor, performs deep copy + * @param rhs The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(const CodeSequenceMacro& rhs); + + /** Convenience constructor to set initial values + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + * @param codeValue The code value + * @param codingSchemeDesignator The coding scheme designator + * @param codeMeaning The code meaning + * @param codingSchemeVersion The coding scheme version (might be empty if + * coding scheme is unique) + */ + CodeSequenceMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent, + const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion = ""); + + /** Convenience constructor to set initial values + * @param codeValue The code value + * @param codingSchemeDesignator The coding scheme designator + * @param codeMeaning The code meaning + * @param codingSchemeVersion The coding scheme version (might be empty if + * coding scheme is unique) + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion = "", + IODComponent* parent = NULL); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the component ("CodeSequenceMacro") + */ + virtual OFString getName() const; + + /** Virtual Destructor + */ + virtual ~CodeSequenceMacro(); + + /** Check whether this component's data satisfies the underlying + * rules. In this case, it is only checked that Designator, Value and + * Meaning of the code are set. + * @param quiet If OFTrue, not error / warning messages will be produced. Only + * the returned error code will indicate error or OK. Per default, + * logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Get Code Value, URL Code Value or Long Code Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @param autoTag If OFTrue, this method will consider tags + * Code Value (0008,0100) + * URN Code Code Value (0008,0120) and + * Long Code Value (0008,0119) and + * in this order and will return once it finds that tag, + * even if the related value is empty. + * If OFFalse, getCodeValue() only returns the value + * found in Code Value (0008,0100). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodeValue(OFString& value, const signed long pos = 0, const OFBool autoTag = OFTrue); + + /** Get URN Code Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getURNCodeValue(OFString& value, const signed long pos = 0); + + /** Get Long Code Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLongCodeValue(OFString& value, const signed long pos = 0); + + /** Get Coding Scheme Designator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodingSchemeDesignator(OFString& value, const signed long pos = 0); + + /** Get Coding Scheme Version + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodingSchemeVersion(OFString& value, const signed long pos = 0); + + /** Get Code Meaning + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodeMeaning(OFString& value, const signed long pos = 0); + + /** Returns whether code is empty, i.e. no component of the Code Sequence Macro + * is set. This can be used in order to find out whether someone actually + * wanted to fill in a valid code as opposed of leaving it unset. + * @return OFTrue if no component of this class is set, OFFalse otherwise. + */ + virtual OFBool empty(); + + /** Set Code Value + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @param autoTag If OFTrue, it is determined automatically if + * tag Code Value, URN Code Value or Long Code Value is used. + * If OFFalse, the classic Code Value is used. + * Default is OFTrue. + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition + setCodeValue(const OFString& value, const OFBool checkValue = OFTrue, const OFBool autoTag = OFTrue); + + /** Set URN Code Value + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setURNCodeValue(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Long Code Value + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setLongCodeValue(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Coding Scheme Designator + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodingSchemeDesignator(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Coding Scheme Version + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodingSchemeVersion(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Code Meaning + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodeMeaning(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set all values in this class conveniently + * @param value Code Value to set + * @param scheme Coding Scheme Designator to set + * @param meaning Code Meaning to set + * @param schemeVersion The Coding Scheme Designator version to set + * (optional) + * @param checkValue If OFTrue, VM and VR of values is checked + * @param autoTag If OFTrue, it is determined automatically if + * tag Code Value, URN Code Value or Long Code Value is used. + * If OFFalse, the classic Code Value is used. + * Default is OFTrue. + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition set(const OFString& value, + const OFString& scheme, + const OFString& meaning, + const OFString& schemeVersion = "", + const OFBool checkValue = OFTrue, + const OFBool autoTag = OFTrue); + + /** Returns string representation reflecting the coded value. + * Mostly useful for debugging purposes. + * @return String representing the coded value + */ + virtual OFString toString(); - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - CodeSequenceMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - CodeSequenceMacro(IODComponent* parent = NULL); - - /** Copy Constructor, performs deep copy - * @param rhs The parent of the IOD component (NULL if none or unknown) - */ - CodeSequenceMacro(const CodeSequenceMacro& rhs); - - /** Convenience constructor to set initial values - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - * @param codeValue The code value - * @param codingSchemeDesignator The coding scheme designator - * @param codeMeaning The code meaning - * @param codingSchemeVersion The coding scheme version (might be empty if - * coding scheme is unique) - */ - CodeSequenceMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent, - const OFString& codeValue, - const OFString& codingSchemeDesignator, - const OFString& codeMeaning, - const OFString& codingSchemeVersion = ""); - - /** Convenience constructor to set initial values - * @param codeValue The code value - * @param codingSchemeDesignator The coding scheme designator - * @param codeMeaning The code meaning - * @param codingSchemeVersion The coding scheme version (might be empty if - * coding scheme is unique) - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - CodeSequenceMacro(const OFString& codeValue, - const OFString& codingSchemeDesignator, - const OFString& codeMeaning, - const OFString& codingSchemeVersion = "", - IODComponent* parent = NULL); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of macro - * @return Name of the component ("CodeSequenceMacro") - */ - virtual OFString getName() const; - - /** Virtual Destructor - */ - virtual ~CodeSequenceMacro(); - - /** Get Code Value - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCodeValue(OFString &value, - const signed long pos = 0); - - /** Get Coding Scheme Designator - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCodingSchemeDesignator(OFString &value, - const signed long pos = 0); - - /** Get Coding Scheme Version - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCodingSchemeVersion(OFString &value, - const signed long pos = 0); - - /** Get Code Meaning - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCodeMeaning(OFString &value, - const signed long pos = 0); - - /** Returns whether code is empty, i.e. no component of the Code Sequence Macro - * is set. This can be used in order to find out whether someone actually - * wanted to fill in a valid code as opposed of leaving it unset. - * @return OFTrue if no component of this class is set, OFFalse otherwise. - */ - virtual OFBool empty(); - - /** Set Code Value - * @param value The value to set - * @param checkValue If OFTrue, VM and VR of value are checked - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setCodeValue(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Coding Scheme Designator - * @param value The value to set - * @param checkValue If OFTrue, VM and VR of value are checked - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setCodingSchemeDesignator(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Coding Scheme Version - * @param value The value to set - * @param checkValue If OFTrue, VM and VR of value are checked - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setCodingSchemeVersion(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Code Meaning - * @param value The value to set - * @param checkValue If OFTrue, VM and VR of value are checked - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setCodeMeaning(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set all values in this class conveniently - * @param value Code Value to set - * @param scheme Coding Scheme Designator to set - * @param meaning Code Meaning to set - * @param schemeVersion The Coding Scheme Designator version to set - * (optional) - * @param checkValue If OFTrue, VM and VR of values is checked - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition set(const OFString &value, - const OFString &scheme, - const OFString &meaning, - const OFString &schemeVersion = "", - const OFBool checkValue = OFTrue); - - virtual OFString toString(); - +protected: + /** Deletes all out of the the following list of tags: + * Code Value, Long Code Value and URN Code Value + * @param keepTag The tag to be keep + */ + void deleteUnusedCodeValues(const DcmTagKey& keepTag); }; - /** Code with Modifier(s). Represents the combination of a Code Sequence Macro * that is amended by a Modifier Code Sequence with one or more items. The * VM and requirement type of the Modifier Code Sequence can be configured, as @@ -217,262 +271,244 @@ class DCMTK_DCMIOD_EXPORT CodeWithModifiers : public CodeSequenceMacro { public: - - /** Constructor - * @param modifierType Denotes type of Modifier Code Sequence (i.e. 1, 1C, - * 2, 2C or 3) - * @param modifierVM Denotes how many items are allowed in the Modifier Code - * Sequence - * @param modifierSeq Tag of the sequence that holds the modifier codes. - * The default is the Modifier Code Sequence. - */ - CodeWithModifiers(const OFString& modifierType, - const OFString& modifierVM = "1-n", - const DcmTagKey& modifierSeq = DCM_ModifierCodeSequence); - - /** Copy constructor, performs deep copy. - * @param rhs The component to be copied from - */ - CodeWithModifiers(const CodeWithModifiers& rhs); - - /** Assignment operator, performs deep copy. - * @param rhs The component to be assigned from - * @return Reference to this object - */ - CodeWithModifiers& operator=(const CodeWithModifiers& rhs); - - /** Virtual Destructor, frees memory - */ - virtual ~CodeWithModifiers(); - - /** Clear all attributes from the data that are handled by this component. - * An attribute is considered belonging to the module if there are rules - * marked as belonging to this module via the rule's module name. - */ - void clearData(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get rules handled by this module - * @return The rules - */ - OFshared_ptr getRules() - { - return m_Rules; - } - - /** Get name of component - * @return Name of the component - */ - virtual OFString getName() const; - - /** Get modifier code denoted by index - * @param index Index of modifier code to get (first modifier = 0) - * @return Code if modifier with index exists, NULL otherwise - */ - virtual CodeSequenceMacro* getModifier(const size_t index = 0); - - /** Adds modifier code - * @param modifier The code to be added - * @return EC_Normal if adding was successful, error otherwise - */ - virtual OFCondition addModifier(const CodeSequenceMacro& modifier); - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Check whether this component's data satisfies the underlying - * rules - * @param quiet If OFTrue, not error / warning messages will be produced. Only - * the returned error code will indicate error or OK. Per default, - * logging output is produced (OFFalse). - * @result EC_Normal if rules are satisfied, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Comparison operator for IOD Components - * @param rhs The right hand side of the comparison - * @return 0, if the given object is equal to this object, other value otherwise - */ - virtual int compare(const IODComponent& rhs) const; + /** Constructor + * @param modifierType Denotes type of Modifier Code Sequence (i.e. 1, 1C, + * 2, 2C or 3) + * @param modifierVM Denotes how many items are allowed in the Modifier Code + * Sequence + * @param modifierSeq Tag of the sequence that holds the modifier codes. + * The default is the Modifier Code Sequence. + */ + CodeWithModifiers(const OFString& modifierType, + const OFString& modifierVM = "1-n", + const DcmTagKey& modifierSeq = DCM_ModifierCodeSequence); + + /** Copy constructor, performs deep copy. + * @param rhs The component to be copied from + */ + CodeWithModifiers(const CodeWithModifiers& rhs); + + /** Assignment operator, performs deep copy. + * @param rhs The component to be assigned from + * @return Reference to this object + */ + CodeWithModifiers& operator=(const CodeWithModifiers& rhs); + + /** Virtual Destructor, frees memory + */ + virtual ~CodeWithModifiers(); + + /** Clear all attributes from the data that are handled by this component. + * An attribute is considered belonging to the module if there are rules + * marked as belonging to this module via the rule's module name. + */ + void clearData(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get rules handled by this module + * @return The rules + */ + OFshared_ptr getRules() + { + return m_Rules; + } + + /** Get name of component + * @return Name of the component + */ + virtual OFString getName() const; + + /** Get modifier code denoted by index + * @param index Index of modifier code to get (first modifier = 0) + * @return Code if modifier with index exists, NULL otherwise + */ + virtual CodeSequenceMacro* getModifier(const size_t index = 0); + + /** Adds modifier code + * @param modifier The code to be added + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition addModifier(const CodeSequenceMacro& modifier); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. Only + * the returned error code will indicate error or OK. Per default, + * logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Comparison operator for IOD Components + * @param rhs The right hand side of the comparison + * @return 0, if the given object is equal to this object, other value otherwise + */ + virtual int compare(const IODComponent& rhs) const; private: + /// Private undefined default constructor + CodeWithModifiers(); - /// Private undefined default constructor - CodeWithModifiers(); + /// Items of Modifier Code Sequence + OFVector m_Modifiers; - /// Items of Modifier Code Sequence - OFVector m_Modifiers; + /// Type 1,2,3,1C or 2C + OFString m_ModifierType; - /// Type 1,2,3,1C or 2C - OFString m_ModifierType; + /// 1, 1-n, 2-2n, ... + OFString m_ModifierVM; - /// 1, 1-n, 2-2n, ... - OFString m_ModifierVM; - - /// The sequence tag key that contains the modifier codes - DcmTagKey m_CodeModifierSeq; + /// The sequence tag key that contains the modifier codes + DcmTagKey m_CodeModifierSeq; }; - - /** Class implementing the SOP Instance Reference Macro */ class DCMTK_DCMIOD_EXPORT SOPInstanceReferenceMacro : public IODComponent { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - SOPInstanceReferenceMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - SOPInstanceReferenceMacro(IODComponent* parent = NULL); - - /** Virtual Destructor - */ - virtual ~SOPInstanceReferenceMacro(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of macro - * @return Name of the module ("SOPInstanceReferenceMacro") - */ - virtual OFString getName() const; - - /** Get Referenced SOP Class UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferencedSOPClassUID(OFString &value, - const signed long pos = 0); - /** Get Referenced SOP Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferencedSOPInstanceUID(OFString &value, - const signed long pos = 0); - /** Set Referenced SOP Class UID - * @param value The value to set - * @param checkValue If OFTrue, the value is checked regarding VM and VR - * @return EC_Normal, if successful, error otherwise - */ - virtual OFCondition setReferencedSOPClassUID(const OFString& value, - const OFBool checkValue = OFTrue); - /** Set Referenced SOP Instance UID - * @param value The value to set - * @param checkValue If OFTrue, the value is checked regarding VM and VR - * @return EC_Normal, if successful, error otherwise - */ - virtual OFCondition setReferencedSOPInstanceUID(const OFString& value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + SOPInstanceReferenceMacro(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + SOPInstanceReferenceMacro(IODComponent* parent = NULL); + + /** Virtual Destructor + */ + virtual ~SOPInstanceReferenceMacro(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("SOPInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Get Referenced SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSOPClassUID(OFString& value, const signed long pos = 0); + /** Get Referenced SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSOPInstanceUID(OFString& value, const signed long pos = 0); + /** Set Referenced SOP Class UID + * @param value The value to set + * @param checkValue If OFTrue, the value is checked regarding VM and VR + * @return EC_Normal, if successful, error otherwise + */ + virtual OFCondition setReferencedSOPClassUID(const OFString& value, const OFBool checkValue = OFTrue); + /** Set Referenced SOP Instance UID + * @param value The value to set + * @param checkValue If OFTrue, the value is checked regarding VM and VR + * @return EC_Normal, if successful, error otherwise + */ + virtual OFCondition setReferencedSOPInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); }; - /** Class representing the Series and Instance Reference Macro */ class DCMTK_DCMIOD_EXPORT IODSeriesAndInstanceReferenceMacro : public IODComponent { public: - - // Forward declaration - class ReferencedSeriesItem; - - /** Constructor - * @param data The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - IODSeriesAndInstanceReferenceMacro(OFshared_ptr data, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent component of this class (if applicable, might - * be NULL) - */ - IODSeriesAndInstanceReferenceMacro(IODComponent* parent = NULL); - - /** Virtual Destructor - */ - virtual ~IODSeriesAndInstanceReferenceMacro(); - - /** Read Series and Instance Reference Macro from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is deleted before - * reading (default) - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write Series and Instance Reference Macro to given item - * @param destination The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Get name of module ("SeriesAndInstanceReferenceMacro") - * @return Name of the module ("SeriesAndInstanceReferenceMacro") - */ - virtual OFString getName() const; - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Clear (removes) all attributes handled by the modules of this component. - * Rules are not reset. - */ - virtual void clearData(); - - /** Return reference to list of Referenced Series items - * @return Reference to list of Reference Series Items - */ - OFVector& getReferencedSeriesItems(); + // Forward declaration + class ReferencedSeriesItem; + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODSeriesAndInstanceReferenceMacro(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this class (if applicable, might + * be NULL) + */ + IODSeriesAndInstanceReferenceMacro(IODComponent* parent = NULL); + + /** Virtual Destructor + */ + virtual ~IODSeriesAndInstanceReferenceMacro(); + + /** Read Series and Instance Reference Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is deleted before + * reading (default) + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write Series and Instance Reference Macro to given item + * @param destination The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get name of module ("SeriesAndInstanceReferenceMacro") + * @return Name of the module ("SeriesAndInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Return reference to list of Referenced Series items + * @return Reference to list of Reference Series Items + */ + OFVector& getReferencedSeriesItems(); private: + /// Vector with all items of the Referenced Series Sequence + OFVector m_ReferencedSeriesItems; - /// Vector with all items of the Referenced Series Sequence - OFVector m_ReferencedSeriesItems; - - /// Name of this component ("SeriesAndInstanceReferenceMacro") - static const OFString m_ComponentName; - + /// Name of this component ("SeriesAndInstanceReferenceMacro") + static const OFString m_ComponentName; }; - /** Class representing Items from the Referenced Series Sequence: * * [Referenced Series Sequence: (SQ, VM 1-n, Type 1C)] @@ -485,224 +521,205 @@ class DCMTK_DCMIOD_EXPORT IODSeriesAndInstanceReferenceMacro::ReferencedSeriesIt { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - ReferencedSeriesItem(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent component of this class (if applicable, might - * be NULL) - */ - ReferencedSeriesItem(IODComponent* parent = NULL); - - /** Destructor - */ - virtual ~ReferencedSeriesItem(); - - /** Clear (removes) all attributes handled by the modules of this component. - * Rules are not reset. - */ - virtual void clearData(); - - /** Read Referenced Series Sequence item data from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading - * @return EC_Normal if data could be read successfully, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this Referenced Series Sequence item data to given item - * @param destination The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values. - */ - virtual void resetRules(); - - /** Get name of module ("SeriesAndInstanceReferenceMacro") - * @return Name of the module ("SeriesAndInstanceReferenceMacro") - */ - virtual OFString getName() const; - - /** Get Series Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Set Series Instance UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR and VM if enabled - * @return status EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesInstanceUID(const OFString& value, - const OFBool checkValue = OFTrue); - - virtual OFCondition addReference(const OFString& sopClassUID, - const OFString& sopInstanceUID); - - /** Get content of the Referenced Instance Sequence - * @return Reference to the Referenced Instance Sequence content - */ - virtual OFVector& getReferencedInstanceItems(); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + ReferencedSeriesItem(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this class (if applicable, might + * be NULL) + */ + ReferencedSeriesItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~ReferencedSeriesItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read Referenced Series Sequence item data from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading + * @return EC_Normal if data could be read successfully, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write this Referenced Series Sequence item data to given item + * @param destination The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module ("SeriesAndInstanceReferenceMacro") + * @return Name of the module ("SeriesAndInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Get Series Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Set Series Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); + + virtual OFCondition addReference(const OFString& sopClassUID, const OFString& sopInstanceUID); + + /** Get content of the Referenced Instance Sequence + * @return Reference to the Referenced Instance Sequence content + */ + virtual OFVector& getReferencedInstanceItems(); private: + /// The name of this component ("SeriesAndInstanceReferenceMacro") + static const OFString m_ComponentName; - /// The name of this component ("SeriesAndInstanceReferenceMacro") - static const OFString m_ComponentName; - - /// Vector containing the data of all items of the Referenced Instance Sequence - OFVector m_ReferencedInstanceSequence; + /// Vector containing the data of all items of the Referenced Instance Sequence + OFVector m_ReferencedInstanceSequence; }; - /** Class representing the Image SOP Instance Reference Macro */ class DCMTK_DCMIOD_EXPORT ImageSOPInstanceReferenceMacro : public SOPInstanceReferenceMacro { public: - - /** Constructor - */ - ImageSOPInstanceReferenceMacro(); - - /** Virtual Destructor - */ - virtual ~ImageSOPInstanceReferenceMacro(); - - /** Creates an ImageSOPInstanceReferenceMacro object without frame/segment - * reference from required information. - * @param sopClassUID The SOP Class UID of the reference - * @param sopInstanceUID The SOP Instance UID of the reference - * @param result Returns the resulting object if successful, NULL otherwise - * @return EC_Normal if creation was successful, error code otherwise - */ - static OFCondition create(const OFString& sopClassUID, - const OFString& sopInstanceUID, - ImageSOPInstanceReferenceMacro*& result); - - /** Creates an ImageSOPInstanceReferenceMacro object with frame or segment - * references from required information. - * @param sopClassUID The SOP Class UID of the reference - * @param sopInstanceUID The SOP Instance UID of the reference - * @param refFramesOrSegments Reference to specific frames of an image or - * segments of a Segmentation object. The decision (image or - * segmentation) is based on the SOP Class; in case it is the - * Segmentation Storage SOP Class, the parameter is interpreted - * as segment references, otherwise as frame references. If this - * parameter is provided empty, then no frame/segment reference is - * set at all. - * @param result Returns the resulting object if successful, NULL otherwise - * @return EC_Normal if creation was successful, error code otherwise - */ - static OFCondition create(const OFString& sopClassUID, - const OFString& sopInstanceUID, - const OFVector& refFramesOrSegments, - ImageSOPInstanceReferenceMacro*& result); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type - * @param rhs The right hand side of the comparison - * @return 0 If the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. Also returned if rhs cannot be - * casted to DcmAttributeTag. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const IODComponent& rhs) const; - - /** Clear data - */ - virtual void clear(); - - /** Read Image SOP Instance Reference Macro from given item - * @param source The item to read from - * @param clearOldData If OFTrue (default), old data is cleared before reading - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write Image SOP Instance Reference Macrom to given item - * @param item The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get Referenced Frame Number - * @param values Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferencedFrameNumber(OFVector &values); - - /** Get Referenced Segment Number - * @param values Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferencedSegmentNumber(OFVector &values); - - /** Set Referenced Frame Number - * @param values The frame numbers that shoule be referenced - * @param checkValue If OFTrue (default) the given values will be checked - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition setReferencedFrameNumber(const OFVector& values, - const OFBool checkValue = OFTrue); - /** Add a Referenced Frame Number - * @param value The frame number to add - * @param checkValue If OFTrue, consistency checks are performed (as possible) - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition addReferencedFrameNumber(const Uint16& value, - const OFBool checkValue = OFTrue); - /** Set the Referenced Segment Numbers - * @param values The segment numbers to add - * @param checkValue If OFTrue, consistency checks are performed (as possible) - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition setReferencedSegmentNumber(const OFVector& values, - const OFBool checkValue = OFTrue); - - /** Add a Referenced Segment Number - * @param value The segment number to add - * @param checkValue If OFTrue, consistency checks are performed (as possible) - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition addReferencedSegmentNumber(const Uint16& value, - const OFBool checkValue = OFTrue); + /** Constructor + */ + ImageSOPInstanceReferenceMacro(); + + /** Virtual Destructor + */ + virtual ~ImageSOPInstanceReferenceMacro(); + + /** Creates an ImageSOPInstanceReferenceMacro object without frame/segment + * reference from required information. + * @param sopClassUID The SOP Class UID of the reference + * @param sopInstanceUID The SOP Instance UID of the reference + * @param result Returns the resulting object if successful, NULL otherwise + * @return EC_Normal if creation was successful, error code otherwise + */ + static OFCondition + create(const OFString& sopClassUID, const OFString& sopInstanceUID, ImageSOPInstanceReferenceMacro*& result); + + /** Creates an ImageSOPInstanceReferenceMacro object with frame or segment + * references from required information. + * @param sopClassUID The SOP Class UID of the reference + * @param sopInstanceUID The SOP Instance UID of the reference + * @param refFramesOrSegments Reference to specific frames of an image or + * segments of a Segmentation object. The decision (image or + * segmentation) is based on the SOP Class; in case it is the + * Segmentation Storage SOP Class, the parameter is interpreted + * as segment references, otherwise as frame references. If this + * parameter is provided empty, then no frame/segment reference is + * set at all. + * @param result Returns the resulting object if successful, NULL otherwise + * @return EC_Normal if creation was successful, error code otherwise + */ + static OFCondition create(const OFString& sopClassUID, + const OFString& sopInstanceUID, + const OFVector& refFramesOrSegments, + ImageSOPInstanceReferenceMacro*& result); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type + * @param rhs The right hand side of the comparison + * @return 0 If the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if rhs cannot be + * casted to DcmAttributeTag. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const IODComponent& rhs) const; + + /** Clear data + */ + virtual void clear(); + + /** Read Image SOP Instance Reference Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue (default), old data is cleared before reading + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write Image SOP Instance Reference Macrom to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get Referenced Frame Number + * @param values Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedFrameNumber(OFVector& values); + + /** Get Referenced Segment Number + * @param values Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSegmentNumber(OFVector& values); + + /** Set Referenced Frame Number + * @param values The frame numbers that shoule be referenced + * @param checkValue If OFTrue (default) the given values will be checked + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition setReferencedFrameNumber(const OFVector& values, const OFBool checkValue = OFTrue); + /** Add a Referenced Frame Number + * @param value The frame number to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition addReferencedFrameNumber(const Uint16& value, const OFBool checkValue = OFTrue); + /** Set the Referenced Segment Numbers + * @param values The segment numbers to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition setReferencedSegmentNumber(const OFVector& values, const OFBool checkValue = OFTrue); + + /** Add a Referenced Segment Number + * @param value The segment number to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition addReferencedSegmentNumber(const Uint16& value, const OFBool checkValue = OFTrue); private: + // DICOM attributes. + // The comments for each attribute describe "Name: (VR, VM, Type)". + // See DICOM standard for further reference. - // DICOM attributes. - // The comments for each attribute describe "Name: (VR, VM, Type)". - // See DICOM standard for further reference. - - /// Referenced Frame Number: (IS, 1-n, 1C) - DcmIntegerString ReferencedFrameNumber; - - /// Referenced Segment Number: (US, 1-n, 1C) - DcmUnsignedShort ReferencedSegmentNumber; + /// Referenced Frame Number: (IS, 1-n, 1C) + DcmIntegerString ReferencedFrameNumber; + /// Referenced Segment Number: (US, 1-n, 1C) + DcmUnsignedShort ReferencedSegmentNumber; }; - /** Class representing the Primary Anatomic Structure Macro */ typedef CodeWithModifiers PrimaryAnatomicStructureMacro; @@ -713,584 +730,541 @@ class DCMTK_DCMIOD_EXPORT GeneralAnatomyMacro { public: - - /** Constructor - * @param type Type of Anatomic Region Sequence. Permitted values: If 1, - * the class represents the "General Anatomy Mandatory Macro", if - * type 2 then it behaves like the "General Anatomy Required Macro", - * and type 3 like the "General Anatomy Optional Macro". Other values - * are interpreted as type 3 (optional). - */ - GeneralAnatomyMacro(const OFString& type); - - /** Copy constructor, creates deep copy. - * @param rhs The macro to copy from - */ - GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs); - - /** Virtual destructor - */ - virtual ~GeneralAnatomyMacro(); - - /** Clear (removes) all attributes handled by the modules of this component. - */ - virtual void clearData(); - - /** Check whether this component's data satisfies the underlying - * rules - * @param quiet If OFTrue, not error / warning messages will be produced. - * Only the returned error code will indicate error or OK. Per - * default, logging output is produced (OFFalse). - * @result EC_Normal if rules are satisfied, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Return Anatomic Region - * @return Reference to Anatomic Region Code - */ - virtual CodeSequenceMacro& getAnatomicRegion(); - - /** Return Anatomic Region Modifier Codes - * @return Reference to Anatomic Region Modifier codes - */ - virtual OFVector& getAnatomicRegionModifier(); - - /** Return anatomic structure - * @return Reference to anatomic structure macro - */ - virtual PrimaryAnatomicStructureMacro& getPrimaryAnatomicStructure(); - - /** Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from - * given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading, - * otherwise it is kept/overwritten. - * @return EC_Normal if no error, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write Anatomic Region Sequence and Primary Anatomic Structure Macro to - * given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Assignment operator (performs deep copy) - * @param rhs The macro to copy from - * @return Reference to "this" object - */ - GeneralAnatomyMacro& operator=(const GeneralAnatomyMacro &rhs); - - /** Comparison operator that compares the normalized value of this object - * with a given object of the same type, i.e.\ the elements within both - * objects (this and rhs parameter) are compared by value. - * @param rhs the right hand side of the comparison - * @return 0 if the object values are equal. - * -1 if either the value of the first component that does not match - * is lower in the rhs object, or all compared components match - * but the rhs component is shorter. - * 1 if either the value of the first component that does not match - * is greater in the rhs object, or all compared components match - * but the rhs component is longer. - */ - virtual int compare(const GeneralAnatomyMacro& rhs) const; + /** Constructor + * @param type Type of Anatomic Region Sequence. Permitted values: If 1, + * the class represents the "General Anatomy Mandatory Macro", if + * type 2 then it behaves like the "General Anatomy Required Macro", + * and type 3 like the "General Anatomy Optional Macro". Other values + * are interpreted as type 3 (optional). + */ + GeneralAnatomyMacro(const OFString& type); + + /** Copy constructor, creates deep copy. + * @param rhs The macro to copy from + */ + GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs); + + /** Virtual destructor + */ + virtual ~GeneralAnatomyMacro(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return Anatomic Region + * @return Reference to Anatomic Region Code + */ + virtual CodeSequenceMacro& getAnatomicRegion(); + + /** Return Anatomic Region Modifier Codes + * @return Reference to Anatomic Region Modifier codes + */ + virtual OFVector& getAnatomicRegionModifier(); + + /** Return anatomic structure + * @return Reference to anatomic structure macro + */ + virtual PrimaryAnatomicStructureMacro& getPrimaryAnatomicStructure(); + + /** Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from + * given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten. + * @return EC_Normal if no error, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write Anatomic Region Sequence and Primary Anatomic Structure Macro to + * given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Assignment operator (performs deep copy) + * @param rhs The macro to copy from + * @return Reference to "this" object + */ + GeneralAnatomyMacro& operator=(const GeneralAnatomyMacro& rhs); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * objects (this and rhs parameter) are compared by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const GeneralAnatomyMacro& rhs) const; private: + /// Type (1,2,3) of Anatomic Region Sequence. + OFString m_Type; - /// Type (1,2,3) of Anatomic Region Sequence. - OFString m_Type; + /// Anatomic Region Sequence (SQ, 1, 1) (Code Sequence Macro within item of + /// Anatomic Region Sequence)) + CodeSequenceMacro m_AnatomicRegion; - /// Anatomic Region Sequence (SQ, 1, 1) (Code Sequence Macro within item of - /// Anatomic Region Sequence)) - CodeSequenceMacro m_AnatomicRegion; + /// Anatomic Region Modifier Macro (within item of Anatomic Region Sequence) + OFVector m_AnatomicRegionModifier; - /// Anatomic Region Modifier Macro (within item of Anatomic Region Sequence) - OFVector m_AnatomicRegionModifier; - - /// Primary Anatomic Structure Macro (on the same level as Anatomic - /// Region Sequence) - PrimaryAnatomicStructureMacro m_PrimaryAnatomicStructure; + /// Primary Anatomic Structure Macro (on the same level as Anatomic + /// Region Sequence) + PrimaryAnatomicStructureMacro m_PrimaryAnatomicStructure; }; - /** Class representing the Algorithm Identification Macro */ class DCMTK_DCMIOD_EXPORT AlgorithmIdentificationMacro { public: - - /** Constructor - */ - AlgorithmIdentificationMacro(); - - /** Virtual destructor - */ - virtual ~AlgorithmIdentificationMacro(); - - /** Clear (removes) all attributes handled by the modules of this component. - */ - virtual void clearData(); - - /** Perform consistency checks - * @param quiet If OFTrue, not error / warning messages will be produced. - * Only the returned error code will indicate error or OK. Per - * default, logging output is produced (OFFalse). - * @result EC_Normal if rules are satisfied, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Return Algorithm Family Code - * @return Reference to algorithm family code - */ - virtual CodeSequenceMacro& getAlgorithmFamilyCode(); - - /** Get Algorithm Name Code - * @return Algorithm Name Code - */ - virtual CodeSequenceMacro& getAlgorithmNameCode(); - - /** Get Algorithm Name - * @param value Reference variable to store the value to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getAlgorithmName(OFString& value, - const signed long pos = 0); - - /** Get Algorithm Version - * @param value Reference variable to store the value to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getAlgorithmVersion(OFString& value, - const signed long pos = 0); - - /** Get Algorithm Parameters - * @param value Reference variable to store the value to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getAlgorithmParameters(OFString& value, - const signed long pos = 0); - /** Get Algorithm Source - * @param value Reference variable to store the value to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getAlgorithmSource(OFString& value, - const signed long pos = 0); - - /** Set Algorithm Name - * @param value The value to be set - * @param checkValue If OFTrue, the given value is checked - * @return EC_Normal, if value could be set, error otherwise - */ - virtual OFCondition setAlgorithmName(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Algorithm Version - * @param value The value to be set - * @param checkValue If OFTrue, the given value is checked - * @return EC_Normal, if value could be set, error otherwise - */ - virtual OFCondition setAlgorithmVersion(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Algorithm Parameters - * @param value The value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal, if value could be set, error otherwise - */ - virtual OFCondition setAlgorithmParameters(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Algorithm Source - * @param value The value to be set - * @param checkValue If OFTrue, the given value is checked - * @return EC_Normal, if value could be set, error otherwise - */ - virtual OFCondition setAlgorithmSource(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Reads this macro from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading, - * otherwise it is kept/overwritten - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this macro to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /** Constructor + */ + AlgorithmIdentificationMacro(); + + /** Virtual destructor + */ + virtual ~AlgorithmIdentificationMacro(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Perform consistency checks + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return Algorithm Family Code + * @return Reference to algorithm family code + */ + virtual CodeSequenceMacro& getAlgorithmFamilyCode(); + + /** Get Algorithm Name Code + * @return Algorithm Name Code + */ + virtual CodeSequenceMacro& getAlgorithmNameCode(); + + /** Get Algorithm Name + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmName(OFString& value, const signed long pos = 0); + + /** Get Algorithm Version + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmVersion(OFString& value, const signed long pos = 0); + + /** Get Algorithm Parameters + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmParameters(OFString& value, const signed long pos = 0); + /** Get Algorithm Source + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmSource(OFString& value, const signed long pos = 0); + + /** Set Algorithm Name + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Algorithm Version + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmVersion(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Algorithm Parameters + * @param value The value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmParameters(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Algorithm Source + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmSource(const OFString& value, const OFBool checkValue = OFTrue); + + /** Reads this macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write this macro to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); private: + /// Code Sequence Macro from Algorithm Family Code Sequence (single item), + /// (SQ, VM 1, Type 1) + CodeSequenceMacro m_AlgorithmFamilyCode; - /// Code Sequence Macro from Algorithm Family Code Sequence (single item), - /// (SQ, VM 1, Type 1) - CodeSequenceMacro m_AlgorithmFamilyCode; + /// Code Sequence Macro from Algorithm Name Code Sequence (single item) + /// (SQ, VM 1, Type 3) + CodeSequenceMacro m_AlgorithmNameCode; - /// Code Sequence Macro from Algorithm Name Code Sequence (single item) - /// (SQ, VM 1, Type 3) - CodeSequenceMacro m_AlgorithmNameCode; + /// Algorithm Name: (LO, VM 1, Typ 1) + DcmLongString m_AlgorithmName; - /// Algorithm Name: (LO, VM 1, Typ 1) - DcmLongString m_AlgorithmName; + /// Algorithm Version: (LO, VM 1, Typ 1) + DcmLongString m_AlgorithmVersion; - /// Algorithm Version: (LO, VM 1, Typ 1) - DcmLongString m_AlgorithmVersion; + /// Algorithm Parameters: (LT, VM 1, Typ 3) + DcmLongText m_AlgorithmParameters; - /// Algorithm Parameters: (LT, VM 1, Typ 3) - DcmLongText m_AlgorithmParameters; - - /// Algorithm Source: (LO, VM 1, Typ 3) - DcmLongString m_AlgorithmSource; + /// Algorithm Source: (LO, VM 1, Typ 3) + DcmLongString m_AlgorithmSource; }; - /** Content Identification Macro */ class DCMTK_DCMIOD_EXPORT ContentIdentificationMacro { public: - - /** Class representing an Alternate Content Description item - */ - class DCMTK_DCMIOD_EXPORT AlternateContentDescriptionItem - { + /** Class representing an Alternate Content Description item + */ + class DCMTK_DCMIOD_EXPORT AlternateContentDescriptionItem + { public: - - /** Constructor - */ - AlternateContentDescriptionItem(); - - /** Virtual destructor - */ - virtual ~AlternateContentDescriptionItem(); - - /** Clear (removes) all attributes handled by the modules of this component. - */ - virtual void clearData(); - - /** Get Content Description - * @param value Reference variable to store the value to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition getContentDescription(OFString& value, - const signed long pos = 0); - /** Get Language Code - * @return Reference to the language code - */ - virtual CodeSequenceMacro& getLanguageCode(); - - /** Set Content Description - * @param value The value to set - * @param checkValue If OFTrue, consistency check is performed - * @result EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setContentDescription(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Read Alternate Content Description Sequence item from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading, - * otherwise it is kept/overwritten - * @result EC_Normal, if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write alternate content description item to given item - * @param item The item to write to - * @result EC_Normal, if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /** Constructor + */ + AlternateContentDescriptionItem(); + + /** Virtual destructor + */ + virtual ~AlternateContentDescriptionItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Get Content Description + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition getContentDescription(OFString& value, const signed long pos = 0); + /** Get Language Code + * @return Reference to the language code + */ + virtual CodeSequenceMacro& getLanguageCode(); + + /** Set Content Description + * @param value The value to set + * @param checkValue If OFTrue, consistency check is performed + * @result EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Read Alternate Content Description Sequence item from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten + * @result EC_Normal, if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write alternate content description item to given item + * @param item The item to write to + * @result EC_Normal, if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); private: - - /// Content Description: (LO, VM 1, Type 1) - DcmLongString m_ContentDescription; - - /// Item of Language Code Sequence: (SQ, VM 1, Type 1) - CodeSequenceMacro m_LanguageCode; - }; - - /** Constructor - */ - ContentIdentificationMacro(); - - /** Constructor initializing basic data - * @param instanceNumber Instance Number - * @param contentLabel Content Label - * @param contentDescription Content Description, may be empty - * @param contentCreatorName Content Creator's Name, may be empty - */ - ContentIdentificationMacro(const OFString& instanceNumber, - const OFString& contentLabel, - const OFString& contentDescription, - const OFString& contentCreatorName); - - /** Copy constructor - * @param rhs The macro to copy from (deep copy) - */ - ContentIdentificationMacro(const ContentIdentificationMacro& rhs); - - /** Create Content Identification Macro with minimally required data. - * @param instanceNumber Instance Number - * @param contentLabel Content Label - * @param contentDescription Content Description, may be empty - * @param contentCreatorName Content Creator's Name, may be empty - * @param result Returns created macro if successful, NULL otherwise - * @return EC_Normal if creation was successful, error otherwise - */ - static OFCondition create(const OFString& instanceNumber, - const OFString& contentLabel, - const OFString& contentDescription, - const OFString& contentCreatorName, - ContentIdentificationMacro*& result); - - /** Assignment operator (deep copy) - * @param rhs The macro to copy from - * @return Reference to "this" object - */ - ContentIdentificationMacro& operator=(const ContentIdentificationMacro& rhs); - - /** Virtual destructor - */ - virtual ~ContentIdentificationMacro(); - - /** Get rules for this data structure - * @return Reference to the rules - */ - virtual IODRules& getIODRules(); - - /** Clear (removes) all attributes handled by the modules of this component. - */ - virtual void clearData(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of macro - * @return Name of the module ("ContentIdentificationMacro") - */ - virtual OFString getName() const; - - - /** Check whether this component's data satisfies the underlying - * rules - * @param quiet If OFTrue, not error / warning messages will be produced. - * Only the returned error code will indicate error or OK. Per - * default, logging output is produced (OFFalse). - * @result EC_Normal if rules are satisfied, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Get Instance Number - * @param value Variable to store the result to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getInstanceNumber(OFString& value, - const signed long pos = 0) const; - - /** Get Content Label - * @param value Variable to store the result to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getContentLabel(OFString& value, - const signed long pos = 0) const; - - /** Get Content Description - * @param value Variable to store the result to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getContentDescription(OFString& value, - const signed long pos = 0) const; - - /** Get Alternate Content Description items - * @return Reference to the items - */ - virtual OFVector& getAlternateContentDescription(); - - /** Get Content Creator Name - * @param value Variable to store the result to - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getContentCreatorName(OFString& value, - const signed long pos = 0) const; - - /** Get Content Creator Identification Code - * @return Reference to code - */ - virtual CodeSequenceMacro& getContentCreatorIdentificationCode(); - - /** Set Instance Number - * @param value Value to be set - * @param checkValue If OFTrue, value is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setInstanceNumber(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Content Label - * @param value Value to be set - * @param checkValue If OFTrue, value is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setContentLabel(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Content Description - * @param value Value to be set - * @param checkValue If OFTrue, value is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setContentDescription(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Content Creator Name - * @param value Value to be set - * @param checkValue If OFTrue, value is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setContentCreatorName(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Reads Content Identification Macro from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading, otherwise - * it is kept/overwritten - * @return EC_Normal if reading was successful, an error code otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write Content Identification Macro to given item - * @param item The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /// Content Description: (LO, VM 1, Type 1) + DcmLongString m_ContentDescription; + + /// Item of Language Code Sequence: (SQ, VM 1, Type 1) + CodeSequenceMacro m_LanguageCode; + }; + + /** Constructor + */ + ContentIdentificationMacro(); + + /** Constructor initializing basic data + * @param instanceNumber Instance Number + * @param contentLabel Content Label + * @param contentDescription Content Description, may be empty + * @param contentCreatorName Content Creator's Name, may be empty + */ + ContentIdentificationMacro(const OFString& instanceNumber, + const OFString& contentLabel, + const OFString& contentDescription, + const OFString& contentCreatorName); + + /** Copy constructor + * @param rhs The macro to copy from (deep copy) + */ + ContentIdentificationMacro(const ContentIdentificationMacro& rhs); + + /** Create Content Identification Macro with minimally required data. + * @param instanceNumber Instance Number + * @param contentLabel Content Label + * @param contentDescription Content Description, may be empty + * @param contentCreatorName Content Creator's Name, may be empty + * @param result Returns created macro if successful, NULL otherwise + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition create(const OFString& instanceNumber, + const OFString& contentLabel, + const OFString& contentDescription, + const OFString& contentCreatorName, + ContentIdentificationMacro*& result); + + /** Assignment operator (deep copy) + * @param rhs The macro to copy from + * @return Reference to "this" object + */ + ContentIdentificationMacro& operator=(const ContentIdentificationMacro& rhs); + + /** Virtual destructor + */ + virtual ~ContentIdentificationMacro(); + + /** Get rules for this data structure + * @return Reference to the rules + */ + virtual IODRules& getIODRules(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("ContentIdentificationMacro") + */ + virtual OFString getName() const; + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Get Instance Number + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getInstanceNumber(OFString& value, const signed long pos = 0) const; + + /** Get Content Label + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentLabel(OFString& value, const signed long pos = 0) const; + + /** Get Content Description + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentDescription(OFString& value, const signed long pos = 0) const; + + /** Get Alternate Content Description items + * @return Reference to the items + */ + virtual OFVector& getAlternateContentDescription(); + + /** Get Content Creator Name + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentCreatorName(OFString& value, const signed long pos = 0) const; + + /** Get Content Creator Identification Code + * @return Reference to code + */ + virtual CodeSequenceMacro& getContentCreatorIdentificationCode(); + + /** Set Instance Number + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setInstanceNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Content Label + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentLabel(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Content Description + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Content Creator Name + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentCreatorName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Reads Content Identification Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, otherwise + * it is kept/overwritten + * @return EC_Normal if reading was successful, an error code otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write Content Identification Macro to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); private: + // Instance Number: (IS, VM 1, Type 1) + DcmIntegerString m_InstanceNumber; - // Instance Number: (IS, VM 1, Type 1) - DcmIntegerString m_InstanceNumber; + /// Content Label: (CS, VM 1, Type 1) + DcmCodeString m_ContentLabel; - /// Content Label: (CS, VM 1, Type 1) - DcmCodeString m_ContentLabel; + /// Content Description: (LO, VM 1, Type 1) + DcmLongString m_ContentDescription; - /// Content Description: (LO, VM 1, Type 1) - DcmLongString m_ContentDescription; + // Alternate Content Description Sequence (VM 1-n, Type 3) + OFVector m_AlternateContentDescription; - // Alternate Content Description Sequence (VM 1-n, Type 3) - OFVector m_AlternateContentDescription; + /// Content Creator's Name: (LO, VM 1, Type 2) + DcmPersonName m_ContentCreatorName; - /// Content Creator's Name: (LO, VM 1, Type 2) - DcmPersonName m_ContentCreatorName; + /// Content Creator's Identification Code Sequence + CodeSequenceMacro m_ContentCreatorIdentificationCode; - /// Content Creator's Identification Code Sequence - CodeSequenceMacro m_ContentCreatorIdentificationCode; - - /// IOD rules for this data structure - IODRules m_IODRules; + /// IOD rules for this data structure + IODRules m_IODRules; }; - /** Class representing the HL7 V2 Hierarchic Designator Macro */ class DCMTK_DCMIOD_EXPORT HL7HierarchicDesignatorMacro : public IODComponent { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - HL7HierarchicDesignatorMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - HL7HierarchicDesignatorMacro(IODComponent* parent = NULL); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of macro - * @return Name of the module ("HL7HierarchicDesignatorMacro") - */ - virtual OFString getName() const; - - /** Get Local Namespace Entity ID - * @param value Variable to store the result to - * @param pos The index (0..VM) of the value to get - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getLocalNamespaceEntityID(OFString& value, - const signed long pos = 0) const; - - /** Get Universal Entity ID - * @param value Variable to store the result to - * @param pos The index (0..VM) of the value to get - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getUniversalEntityID(OFString& value, - const signed long pos = 0) const; - - /** Get Universal Entity ID Type - * @param value Variable to store the result to - * @param pos The index (0..VM) of the value to get - * @return EC_Normal if value could be get, error otherwise - */ - virtual OFCondition getUniversalEntityIDType(OFString& value, - const signed long pos = 0) const; - - /** Set Local Namespace Entity ID - * @param value Value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setLocalNamespaceEntityID(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Universal Entity ID - * @param value Value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setUniversalEntityID(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Universal Entity ID Type - * @param value Value to be set - * @param checkValue If OFTrue, value is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setUniversalEntityIDType(const OFString& value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + HL7HierarchicDesignatorMacro(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + HL7HierarchicDesignatorMacro(IODComponent* parent = NULL); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("HL7HierarchicDesignatorMacro") + */ + virtual OFString getName() const; + + /** Get Local Namespace Entity ID + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getLocalNamespaceEntityID(OFString& value, const signed long pos = 0) const; + + /** Get Universal Entity ID + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getUniversalEntityID(OFString& value, const signed long pos = 0) const; + + /** Get Universal Entity ID Type + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getUniversalEntityIDType(OFString& value, const signed long pos = 0) const; + + /** Set Local Namespace Entity ID + * @param value Value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setLocalNamespaceEntityID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Universal Entity ID + * @param value Value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setUniversalEntityID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Universal Entity ID Type + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setUniversalEntityIDType(const OFString& value, const OFBool checkValue = OFTrue); }; /** Class representing the Mandatory View and Slice Progression Direction Macro @@ -1300,69 +1274,65 @@ class DCMTK_DCMIOD_EXPORT MandatoryViewAndSliceProgressionDirectionMacro : publi { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set where this classes rules are added to. If NULL, - * the class creates an empty rule set. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent = NULL); - - /** Clear (removes) all attributes handled by the modules of this component. - */ - virtual void clearData(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of macro - * @return Name of the module ("MandatoryViewAndSliceProgressionDirectionMacro") - */ - virtual OFString getName() const; - - /** Read Mandatory View and Slice Progression Direction Macro from given item - * @param source The item to read from - * @param clearOldData If OFTrue (default), old data is cleared - * before reading - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write Mandatory View and Slice Progression Direction Macro to given item - * @param item The item to write to - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get View Code - * @return Reference to code - */ - virtual CodeSequenceMacro& getViewCode(); - - /** Get View Modifier Code - * @return Reference to code - */ - virtual OFVector& getViewModifierCode(); - + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, + * the class creates an empty rule set. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent = NULL); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("MandatoryViewAndSliceProgressionDirectionMacro") + */ + virtual OFString getName() const; + + /** Read Mandatory View and Slice Progression Direction Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue (default), old data is cleared + * before reading + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write Mandatory View and Slice Progression Direction Macro to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get View Code + * @return Reference to code + */ + virtual CodeSequenceMacro& getViewCode(); + + /** Get View Modifier Code + * @return Reference to code + */ + virtual OFVector& getViewModifierCode(); protected: + /// View Code Sequence (SQ, VM 1, type 1) + CodeSequenceMacro m_ViewCodeSequence; - /// View Code Sequence (SQ, VM 1, type 1) - CodeSequenceMacro m_ViewCodeSequence; - - /// View Modifier Code Sequence (SQ, VM 1-n, type 2C) - OFVector m_ViewModifierCode; + /// View Modifier Code Sequence (SQ, VM 1-n, type 2C) + OFVector m_ViewModifierCode; }; #endif // IODMACRO_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodreferences.h b/dcmiod/include/dcmtk/dcmiod/iodreferences.h index 5d037e2f..abc7ffd7 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodreferences.h +++ b/dcmiod/include/dcmtk/dcmiod/iodreferences.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,9 @@ #define IODREFERENCES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/oflog/oflog.h" #include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/ofvector.h" // Forward declaration class DcmItem; @@ -42,30 +43,30 @@ class DcmItem; */ class DCMTK_DCMIOD_EXPORT IODReference { - public: +public: /// The maximum DICOM entity level that this reference refers to. This is /// mostly used in order to check whether a reference is complete or not. enum MAX_LEVEL { - /// Instance Level - LEVEL_INSTANCE, - /// Series Level - LEVEL_SERIES, - /// Study level - LEVEL_STUDY, - /// Patient level - LEVEL_PATIENT + /// Instance Level + LEVEL_INSTANCE, + /// Series Level + LEVEL_SERIES, + /// Study level + LEVEL_STUDY, + /// Patient level + LEVEL_PATIENT }; /// Type of reference enum TYPE { - /// Generic (or unknown) - GENERIC, - /// Reference to an image object, see also class IODImageReference - IMAGE, - /// Reference to a segmentation object, see also class IDOSegmentationReference - SEGMENT + /// Generic (or unknown) + GENERIC, + /// Reference to an image object, see also class IODImageReference + IMAGE, + /// Reference to a segmentation object, see also class IDOSegmentationReference + SEGMENT }; /** Constructor, creates empty reference, default level is "STUDY" @@ -89,7 +90,10 @@ class DCMTK_DCMIOD_EXPORT IODReference /** Get type of reference. Base class always returns "GENERIC" * @return Returns "GENERIC" type */ - virtual TYPE getType() const {return GENERIC; } + virtual TYPE getType() const + { + return GENERIC; + } /** Check whether this reference is valid, i.e. complete related to its * level. Also in case of UIDs it is checked whether they conform to the @@ -142,14 +146,12 @@ class DCMTK_DCMIOD_EXPORT IODReference MAX_LEVEL m_Level; }; - /** Class representing a reference to an image. Compared to IODReference, this * class also allows to provide references to specific frames */ class DCMTK_DCMIOD_EXPORT IODImageReference : public IODReference { - public: - +public: /** Default constructor, uses level STUDY */ IODImageReference(); @@ -195,7 +197,10 @@ class DCMTK_DCMIOD_EXPORT IODImageReference : public IODReference /** Get type (always returns IMAGE type) * @return Returns IMAGE type */ - virtual TYPE getType() const {return IMAGE; } + virtual TYPE getType() const + { + return IMAGE; + } // Avoid overridden virtual function warning, i.e. tell the compiler that // we want to have both functions to be polymorph and available to the user. @@ -208,11 +213,12 @@ class DCMTK_DCMIOD_EXPORT IODImageReference : public IODReference * such frames. First frame is denoted by 1. * @return OFTrue if initialization was successful, OFFalse otherwise */ - virtual OFBool readFromFile(const OFString& filename, - const OFVector frameNumbers); + virtual OFBool readFromFile(const OFString& filename, const OFVector frameNumbers); /** Destructor */ - virtual ~IODImageReference() {} + virtual ~IODImageReference() + { + } /** Clear reference data */ @@ -222,15 +228,13 @@ class DCMTK_DCMIOD_EXPORT IODImageReference : public IODReference OFVector m_ReferencedFrameNumber; }; - /** Class representing a reference to a Segmentation. Compared to IODReference, * this class also allows to provide references to specific segments by * referencing the value of their Segment Number attribute. */ class DCMTK_DCMIOD_EXPORT IODSegmentationReference : public IODReference { - public: - +public: /** Constructor allowing to set reference level. * @param level The maximum level this reference should deal with */ @@ -248,7 +252,10 @@ class DCMTK_DCMIOD_EXPORT IODSegmentationReference : public IODReference /** Get type (always returns SEGMENT type) * @return Returns SEGMENT type */ - virtual TYPE getType() const {return SEGMENT; } + virtual TYPE getType() const + { + return SEGMENT; + } // Avoid overridden virtual function warning, i.e. tell the compiler that // we want to have both functions to be polymorph and available to the user. @@ -261,12 +268,13 @@ class DCMTK_DCMIOD_EXPORT IODSegmentationReference : public IODReference * contains such Segment Numbers. First segment is 1. * @return OFTrue if initialization was successful, OFFalse otherwise */ - virtual OFBool readFromFile(const OFString& filename, - const OFVector segmentNumbers); + virtual OFBool readFromFile(const OFString& filename, const OFVector segmentNumbers); /** Destructor */ - virtual ~IODSegmentationReference() {} + virtual ~IODSegmentationReference() + { + } /** Clear reference data */ @@ -276,15 +284,13 @@ class DCMTK_DCMIOD_EXPORT IODSegmentationReference : public IODReference OFVector m_ReferencedSegmentNumber; }; - /** Class that holds a set of IODReference instances (or its sub classes) and * offers helper functionality to read and write such references */ class DCMTK_DCMIOD_EXPORT IODReferences { - public: - +public: /** Default constructor */ IODReferences(); @@ -295,6 +301,8 @@ class DCMTK_DCMIOD_EXPORT IODReferences IODReferences(const IODReferences& rhs); /** Assignment operator, copies all provided references + * @param rhs The right hand side of the assignment + * @return Reference to "this" object */ IODReferences& operator=(const IODReferences& rhs); @@ -354,11 +362,9 @@ class DCMTK_DCMIOD_EXPORT IODReferences */ virtual void clearData(); - private: - +private: /// Set of references managed by this class OFVector m_References; }; - #endif // IODREFERENCES_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodrules.h b/dcmiod/include/dcmtk/dcmiod/iodrules.h index 0babf72a..69697bcd 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodrules.h +++ b/dcmiod/include/dcmtk/dcmiod/iodrules.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,22 +23,20 @@ #define IODRULES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofstring.h" -#include "dcmtk/ofstd/ofmap.h" -#include "dcmtk/ofstd/ofcond.h" #include "dcmtk/dcmdata/dctagkey.h" #include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofstring.h" -#define INCLUDE_OSTREAM // for debugging +#define INCLUDE_OSTREAM // for debugging #include "dcmtk/ofstd/ofstdinc.h" - class DcmItem; class DcmTagKey; class DcmElement; class IODRule; - /** Class representing rules for a set of DICOM attributes, e.g.\ for * all attributes of a module, macro or the like. At the moment * attributes within sequences are not yet supported. @@ -47,80 +45,76 @@ class DCMTK_DCMIOD_EXPORT IODRules { public: - - /// iterator type to iterate over rule set - typedef OFMap::iterator iterator; - - /// const iterator type to iterate over rule set - typedef OFMap::const_iterator const_iterator; - - /** Constructor - */ - IODRules(); - - /** Returns deep copy of this object - * @return Deep copy of "this" object - */ - IODRules* clone(); - - /** Return iterator to first rule - * @return Iterator to the first rule - */ - iterator begin(); - - /** Return iterator to last rule - * @return Iterator to the last rule - */ - iterator end(); - - /** Adds rule to this rule set - * @param rule The rule to add (ownership is transferred to this class) - * @param overwriteExisting If OFTrue (default), an existing rule for the - * same attribute (tag) is overwritten, otherwise the rule is not - * taken over (and ownership stays with caller) - * @return OFTrue if rule could be added, error otherwise - */ - virtual OFBool addRule(IODRule* rule, - const OFBool overwriteExisting = OFFalse); - - /** Delete rule by given tag key - * @param key Tag of the attribute rule to be deleted - * @return OFTrue if a rule could be found and deleted, OFFalse otherwise - */ - virtual OFBool deleteRule(const DcmTagKey key); - - /** Get all rules that are marked belonging to a specific module - * @param moduleName The module name (e.g.\ "PatientModule") - * @return Vector with pointers to all the rules belonging to given module - */ - const OFVector getByModule(const OFString& moduleName); - - /** Get a rule by its tag - * @param key The tag to find the rule for - * @return The rule, if found, NULL otherwise - */ - IODRule* getByTag(const DcmTagKey& key) const; - - /** Clear all rules - */ - virtual void clear(); - - /** Dump rules to stream, useful for debugging - * @param out The stream to dump to - */ - virtual void dump(STD_NAMESPACE ostream &out); - - /** Destructor - */ - virtual ~IODRules(); + /// iterator type to iterate over rule set + typedef OFMap::iterator iterator; + + /// const iterator type to iterate over rule set + typedef OFMap::const_iterator const_iterator; + + /** Constructor + */ + IODRules(); + + /** Returns deep copy of this object + * @return Deep copy of "this" object + */ + IODRules* clone(); + + /** Return iterator to first rule + * @return Iterator to the first rule + */ + iterator begin(); + + /** Return iterator to last rule + * @return Iterator to the last rule + */ + iterator end(); + + /** Adds rule to this rule set + * @param rule The rule to add (ownership is transferred to this class) + * @param overwriteExisting If OFTrue (default), an existing rule for the + * same attribute (tag) is overwritten, otherwise the rule is not + * taken over (and ownership stays with caller) + * @return OFTrue if rule could be added, error otherwise + */ + virtual OFBool addRule(IODRule* rule, const OFBool overwriteExisting = OFFalse); + + /** Delete rule by given tag key + * @param key Tag of the attribute rule to be deleted + * @return OFTrue if a rule could be found and deleted, OFFalse otherwise + */ + virtual OFBool deleteRule(const DcmTagKey key); + + /** Get all rules that are marked belonging to a specific module + * @param moduleName The module name (e.g.\ "PatientModule") + * @return Vector with pointers to all the rules belonging to given module + */ + const OFVector getByModule(const OFString& moduleName); + + /** Get a rule by its tag + * @param key The tag to find the rule for + * @return The rule, if found, NULL otherwise + */ + IODRule* getByTag(const DcmTagKey& key) const; + + /** Clear all rules + */ + virtual void clear(); + + /** Dump rules to stream, useful for debugging + * @param out The stream to dump to + */ + virtual void dump(STD_NAMESPACE ostream& out); + + /** Destructor + */ + virtual ~IODRules(); private: - - /// Map that holds all rules, accessible by their tag key - OFMap m_Rules; + /// Map that holds all rules, accessible by their tag key + OFMap m_Rules; }; - /** Class representing a single rule, that refers to a single attribute. * Each rule is uniquely identified by the attribute's tag key and includes * information on the Value Multiplicity (VM) of the attribute, its type @@ -133,125 +127,124 @@ private: class DCMTK_DCMIOD_EXPORT IODRule { public: - - /** Constructor to create a new attribute rule - * @param key The tag key of the attribute - * @param VM The VM of the attribute (notation like in DICOM part 6, - * e.g.\ "1-n"), for sequences the number of items allowed. - * @param type The "IOD type" of the attribute. - * Allowed values "1", "1C", "2", "2C" and "3" - * @param module The module or "component" this attribute belongs to - * @param ie The Information Entity the module belongs to - * @param defaultValue The default value (default: empty) - * @param privateCreator The private creator of the attribute if attribute - * (default: No private creator) - */ - IODRule(const DcmTagKey& key, - const OFString& VM, - const OFString& type, - const OFString& module, - const DcmIODTypes::IOD_IE ie, - const OFString& defaultValue = "", - const OFString& privateCreator = ""); - - /** Return deep copy of this object - * @return Deep copy of "this" object - */ - IODRule* clone(); - - /** Get tag key of the attribute rule - * @return The tag key of the rule - */ - virtual DcmTagKey getTagKey() const; - - /** Get private creator of the related attribute - * @return The private creator of the attribute - */ - virtual OFString getPrivateCreator() const; - - /** The requirement type of the attribute (1, 1C, 2, 2C or 3) - * @return The requirement type of the attribute - */ - virtual OFString getType() const; - - /** The VM of the attribute as noted in the DICOM standard part 6, - * e.g.\ "1-n" or "2". For Sequences (VR SQ) whose VM is always 1 by the - * standard, this denotes the number of items permitted. - * @return The VM (or number of items permitted) - */ - virtual OFString getVM() const; - - /** Get module (or component name) the related attribute belongs to - * @return The module or component name (e.g.\ "PatientModule" or - * "CodeSequenceMacro") - */ - virtual OFString getModule() const; - - /** Get default value of this attribute - * @return The default value (might be empty) - */ - virtual OFString getDefaultValue() const; - - /** Get Information Entity the related attribute belongs to - * @return The Information Entity (might be empty) - */ - virtual DcmIODTypes::IOD_IE getIE() const; - - virtual OFBool setPrivateCreator(const OFString& val); - - virtual OFBool setType(const OFString& val); - - virtual OFBool setVM(const OFString& val); - - virtual OFBool setModule(const OFString& val); - - virtual OFBool setDefaultValue(const OFString& val); - - /** Check whether the given item fulfills the requirements of - * this rule, i.e.\ the related attribute is checked within the - * given item - * @param item The item to check the attribute in - * @param quiet If OFTrue, no error or warning messages will be produced - * but only the return code will indicate OK or error. - * @return EC_Normal if this rule is fulfilled, error otherwise - */ - virtual OFCondition check(DcmItem& item, - const OFBool quiet = OFFalse); - - /** Virtual Destructor - */ - virtual ~IODRule(); + /** Constructor to create a new attribute rule + * @param key The tag key of the attribute + * @param VM The VM of the attribute (notation like in DICOM part 6, + * e.g.\ "1-n"), for sequences the number of items allowed. + * @param type The "IOD type" of the attribute. + * Allowed values "1", "1C", "2", "2C" and "3" + * @param module The module or "component" this attribute belongs to + * @param ie The Information Entity the module belongs to + * @param defaultValue The default value (default: empty) + * @param privateCreator The private creator of the attribute if attribute + * (default: No private creator) + */ + IODRule(const DcmTagKey& key, + const OFString& VM, + const OFString& type, + const OFString& module, + const DcmIODTypes::IOD_IE ie, + const OFString& defaultValue = "", + const OFString& privateCreator = ""); + + /** Return deep copy of this object + * @return Deep copy of "this" object + */ + IODRule* clone(); + + /** Get tag key of the attribute rule + * @return The tag key of the rule + */ + virtual DcmTagKey getTagKey() const; + + /** Get private creator of the related attribute + * @return The private creator of the attribute + */ + virtual OFString getPrivateCreator() const; + + /** The requirement type of the attribute (1, 1C, 2, 2C or 3) + * @return The requirement type of the attribute + */ + virtual OFString getType() const; + + /** The VM of the attribute as noted in the DICOM standard part 6, + * e.g.\ "1-n" or "2". For Sequences (VR SQ) whose VM is always 1 by the + * standard, this denotes the number of items permitted. + * @return The VM (or number of items permitted) + */ + virtual OFString getVM() const; + + /** Get module (or component name) the related attribute belongs to + * @return The module or component name (e.g.\ "PatientModule" or + * "CodeSequenceMacro") + */ + virtual OFString getModule() const; + + /** Get default value of this attribute + * @return The default value (might be empty) + */ + virtual OFString getDefaultValue() const; + + /** Get Information Entity the related attribute belongs to + * @return The Information Entity (might be empty) + */ + virtual DcmIODTypes::IOD_IE getIE() const; + + virtual OFBool setPrivateCreator(const OFString& val); + + virtual OFBool setType(const OFString& val); + + virtual OFBool setVM(const OFString& val); + + virtual OFBool setModule(const OFString& val); + + virtual OFBool setDefaultValue(const OFString& val); + + /** Check whether the given item fulfills the requirements of + * this rule, i.e.\ the related attribute is checked within the + * given item + * @param item The item to check the attribute in + * @param quiet If OFTrue, no error or warning messages will be produced + * but only the return code will indicate OK or error. + * @return EC_Normal if this rule is fulfilled, error otherwise + */ + virtual OFCondition check(DcmItem& item, const OFBool quiet = OFFalse); + + /** Virtual Destructor + */ + virtual ~IODRule(); private: + /// Private undefined default constructor + IODRule(); - /// Private undefined default constructor - IODRule(); - - /// Private undefined copy constructor - IODRule(const IODRule& rhs); + /** Private undefined copy constructor + * @param rhs Right hand side of assignment + */ + IODRule(const IODRule& rhs); - /// Tag key - DcmTagKey m_Key; + /// Tag key + DcmTagKey m_Key; - /// VM, see DcmElement::checkVM() for permitted values (e.g.\ "1-n") - OFString m_VM; + /// VM, see DcmElement::checkVM() for permitted values (e.g.\ "1-n") + OFString m_VM; - /// Requirement type: 1, 1C, 2, 2C or 3 - OFString m_Type; + /// Requirement type: 1, 1C, 2, 2C or 3 + OFString m_Type; - /// Module (e.g.\ "PatientModule" or "component name", e.g.\ "CodeSequenceMacro" - OFString m_Module; + /// Module (e.g.\ "PatientModule" or "component name", e.g.\ "CodeSequenceMacro" + OFString m_Module; - /// The Information Entity the related attribute belongs to according to the - /// DICOM Model of the Real World, e.g.\ "Patient" for the attribute - /// "Patient Name" - DcmIODTypes::IOD_IE m_IE; + /// The Information Entity the related attribute belongs to according to the + /// DICOM Model of the Real World, e.g.\ "Patient" for the attribute + /// "Patient Name" + DcmIODTypes::IOD_IE m_IE; - /// Default value for attribute - OFString m_DefaultValue; + /// Default value for attribute + OFString m_DefaultValue; - /// Private Creator (if private attribute) - OFString m_PrivateCreator; + /// Private Creator (if private attribute) + OFString m_PrivateCreator; }; #endif // IODRULES_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodtypes.h b/dcmiod/include/dcmtk/dcmiod/iodtypes.h index d282ace9..e66e01ef 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodtypes.h +++ b/dcmiod/include/dcmtk/dcmiod/iodtypes.h @@ -23,10 +23,9 @@ #define IODTYPES_H #include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/ioddef.h" #include "dcmtk/oflog/oflog.h" #include "dcmtk/ofstd/ofcond.h" -#include "dcmtk/dcmiod/ioddef.h" -#include "dcmtk/dcmiod/cielabutil.h" // ---------------------------------------------------------------------------- // Define the loggers for this module @@ -36,30 +35,28 @@ extern DCMTK_DCMIOD_EXPORT OFLogger DCM_dcmiodLogger; #define DCMIOD_TRACE(msg) OFLOG_TRACE(DCM_dcmiodLogger, msg) #define DCMIOD_DEBUG(msg) OFLOG_DEBUG(DCM_dcmiodLogger, msg) -#define DCMIOD_INFO(msg) OFLOG_INFO(DCM_dcmiodLogger, msg) -#define DCMIOD_WARN(msg) OFLOG_WARN(DCM_dcmiodLogger, msg) +#define DCMIOD_INFO(msg) OFLOG_INFO(DCM_dcmiodLogger, msg) +#define DCMIOD_WARN(msg) OFLOG_WARN(DCM_dcmiodLogger, msg) #define DCMIOD_ERROR(msg) OFLOG_ERROR(DCM_dcmiodLogger, msg) #define DCMIOD_FATAL(msg) OFLOG_FATAL(DCM_dcmiodLogger, msg) - // ---------------------------------------------------------------------------- // Error constants // ---------------------------------------------------------------------------- -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_WrongSOPClass; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingAttribute; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingSequenceData; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidDimensions; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotInsertFrame; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidPixelData; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidObject; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotDecompress; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_NoSuchRule; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidLaterality; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidElementValue; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidReference; -extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_ReferencesOmitted; - +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_WrongSOPClass; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingAttribute; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingSequenceData; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidDimensions; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotInsertFrame; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidPixelData; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidObject; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotDecompress; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_NoSuchRule; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidLaterality; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidElementValue; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidReference; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_ReferencesOmitted; /** Class that wraps some constant definitions in the context of IODs */ @@ -67,77 +64,76 @@ class DCMTK_DCMIOD_EXPORT DcmIODTypes { public: - - /** Struct representing a single frame - */ - struct Frame - { - /// Array for the pixel data bytes - Uint8* pixData; - /// Number of pixel data bytes (i.e.\ Bits Allocated) - size_t length; - /// Destructor, frees memory - ~Frame() {delete[] pixData;pixData = NULL;} - }; - - /** IOD Information Entities (incomplete list, extended as needed) - */ - enum IOD_IE - { - /// Undefined Information Entity (i.e.\ no value set) - IE_UNDEFINED, - /// Patient Entity - IE_PATIENT, - /// Study Entity - IE_STUDY, - /// Series Entity - IE_SERIES, - /// Frame of Reference Entity - IE_FOR, - /// Equipment Entity - IE_EQUIPMENT, - /// Image Entity - IE_IMAGE, - //// Meta Entity: Instance covering image, waveform, etc. - IE_INSTANCE - }; - - /** Enumerated values for attribute "Laterality" - */ - enum IOD_LATERALITY - { - /// Undefined (e.g.\ value not set) - LATERALITY_UNDEFINED, - /// Left body part - LATERALITY_L, - /// Right body part - LATERALITY_R - }; - - /** Enhanced US Image Module: Image Type (first value) - */ - enum IOD_ENHUSIMAGETYPE - { - /// Unknown - IMAGETYPE_UNKNOWN, - /// ORIGINAL - IMAGETYPE_ORIGINAL, - /// DERIVED - IMAGETYPE_DERIVED - }; - + /** Struct representing a single frame + */ + struct Frame + { + /// Array for the pixel data bytes + Uint8* pixData; + /// Number of pixel data bytes (i.e.\ Bits Allocated) + size_t length; + /// Destructor, frees memory + ~Frame() + { + delete[] pixData; + pixData = NULL; + } + }; + + /** IOD Information Entities (incomplete list, extended as needed) + */ + enum IOD_IE + { + /// Undefined Information Entity (i.e.\ no value set) + IE_UNDEFINED, + /// Patient Entity + IE_PATIENT, + /// Study Entity + IE_STUDY, + /// Series Entity + IE_SERIES, + /// Frame of Reference Entity + IE_FOR, + /// Equipment Entity + IE_EQUIPMENT, + /// Image Entity + IE_IMAGE, + //// Meta Entity: Instance covering image, waveform, etc. + IE_INSTANCE + }; + + /** Enumerated values for attribute "Laterality" + */ + enum IOD_LATERALITY + { + /// Undefined (e.g.\ value not set) + LATERALITY_UNDEFINED, + /// Left body part + LATERALITY_L, + /// Right body part + LATERALITY_R + }; + + /** Enhanced US Image Module: Image Type (first value) + */ + enum IOD_ENHUSIMAGETYPE + { + /// Unknown + IMAGETYPE_UNKNOWN, + /// ORIGINAL + IMAGETYPE_ORIGINAL, + /// DERIVED + IMAGETYPE_DERIVED + }; private: + /** Private undefined default constructor + */ + DcmIODTypes() {}; - /** Private undefined default constructor - */ - DcmIODTypes() {}; - - /** Private undefined destructor - */ - ~DcmIODTypes() {}; - + /** Private undefined destructor + */ + ~DcmIODTypes() {}; }; - #endif // IODTYPES_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodutil.h b/dcmiod/include/dcmtk/dcmiod/iodutil.h index ae0098c2..057082fa 100644 --- a/dcmiod/include/dcmtk/dcmiod/iodutil.h +++ b/dcmiod/include/dcmtk/dcmiod/iodutil.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,17 +23,17 @@ #define IODUTIL_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/oftraits.h" // for OFremove_pointer -#include "dcmtk/ofstd/ofstring.h" -#include "dcmtk/dcmdata/dcelem.h" -#include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dcdatset.h" #include "dcmtk/dcmdata/dcdatutl.h" -#include "dcmtk/ofstd/ofdate.h" -#include "dcmtk/ofstd/oftime.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmiod/ioddef.h" #include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/ofstd/ofdate.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/oftime.h" +#include "dcmtk/ofstd/oftraits.h" // for OFremove_pointer /** Class with helper functions used within the dcmiod module (and beyond) */ @@ -41,909 +41,975 @@ class DCMTK_DCMIOD_EXPORT DcmIODUtil { public: - - /** Get element from dataset and check it for correct value multiplicity - * and type. - * @param dataset DICOM dataset from which the element should be retrieved. - * (Would be 'const' if the methods from 'dcmdata' would also - * (be 'const'.) - * @param delem DICOM element used to store the value (always creates - * a copy of the dataset element's value) - * @param vm Value multiplicity (according to the data dictionary) to be - * checked for. (See DcmElement::checkVM() for a list of valid - * values.) Interpreted as cardinality (number of items) for - * sequence attributes. - * @param type Value type (valid value: "1", "1C", "2", something else - * which is not checked) - * @param moduleName Optional module name to be printed (NULL: no module - * printed at all) - * @return EC_Normal if element could be retrieved and value is correct, - * an error code otherwise - */ - static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement &delem, - const OFString &vm, - const OFString &type, - const char *moduleName = NULL); - - /** Get element from dataset and check it for correct value multiplicity and - * type. - * @param dataset DICOM dataset from which the element should be retrieved. - * (Would be 'const' if the methods from 'dcmdata' would also - * be 'const') - * @param tagKey Tag key of the element to get - * @param delem DICOM element that is set to a copy of the dataset's - * orinal element - * @param vm Value multiplicity (according to the data dictionary) to be - * checked for. (See DcmElement::checkVM() for a list of valid - * values.) Interpreted as cardinality (number of items) for - * sequence attributes. - * @param type Value type (valid value: "1", "1C", "2", something else - * which is not checked) - * @param moduleName Optional module name to be printed (NULL: no module - * printed at all) - * @return EC_Normal if element could be retrieved and value is correct, an - * error code otherwise - */ - static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, - const DcmTagKey& tagKey, - DcmElement*& delem, - const OFString &vm, - const OFString &type, - const char *moduleName = NULL); - - /** Get element from dataset and check it for correct value multiplicity - * and type. - * @param dataset DICOM dataset from which the element should be retrieved. - * (Would be 'const' if the methods from 'dcmdata' would also - * be 'const'.) - * @param delem DICOM element used to store the value (always creates - * a copy of the value from the original element) - * @param rule Rule describing parameters to be checked on element - * @return EC_Normal if element could be retrieved and value is correct, an - * error code otherwise - */ - static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement &delem, - const IODRule* rule); - - /** Get element from dataset and check it for correct value multiplicity - * and type. - * @param dataset DICOM dataset from which the element should be retrieved. - * (Would be 'const' if the methods from 'dcmdata' would also - * be 'const') - * @param delem DICOM element that is set to a copy of the dataset's - * orinal element - * @param rule Rule describing parameters to be checked on element. - * @return EC_Normal if element could be retrieved and value is correct, an - * error code otherwise - */ - static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement*& delem, - const IODRule* rule); - - /** Get current date in DICOM 'DA' format (YYYYMMDD) - * @param dateString String used to store the current date. - * (empty string if current date could not be retrieved) - * @return Resulting character string - */ - static const OFString& currentDate(OFString &dateString); - - /** Get current time in DICOM 'TM' format (HHMMSS) - * The optional UTC notation (e.g.\ +0100) is currently not supported. - * @param timeString String used to store the current time - * (empty string if current time could not be retrieved) - * @return Resulting character string, empty if time could not be retrieved - */ - static const OFString& currentTime(OFString &timeString); - - /** Copy given element to the dataset - * The element is only added if 'result' is EC_Normal. A copy of the given - * element is created, i.e.\ the caller is responsible for deleting the - * original element handed to this function (if desired). - * @param result Reference to status variable (checked before adding and - * updated afterwards!) - * @param dataset Reference to DICOM dataset to which the element should - * be added - * @param delem Reference to DICOM element which should be added; a - * copy is created so caller is responsible for deleting delem (if - * desired). - * @param vm Value multiplicity (according to the data dictionary) to be - * checked for. (See DcmElement::checkVM() for a list of valid - * values.). Interpreted as cardinality (number of items) for - * sequence attributes. - * @param type Value type (valid value: "1", "2" or something else which - * is not checked) - * @param moduleName Optional module name to be printed (NULL: no module - * printed at all) - * @return Current value of 'result', EC_Normal if successful, - * an error code otherwise - */ - static OFCondition copyElementToDataset(OFCondition &result, - DcmItem &dataset, - const DcmElement &delem, - const OFString &vm, - const OFString &type, - const char *moduleName = NULL); - - /** Copy given element to the dataset. The element is only added if 'result' - * is EC_Normal. - * @param result reference to status variable (checked before adding and - * updated afterwards!) - * @param dataset reference to DICOM dataset to which the element - * should be added - * @param delem reference to DICOM element which should be added; the value - * is copied from the original dataset's element - * @param rule Rule describing parameters to be checked on element. - * @return Current value of 'result', EC_Normal if successful, an error code - * otherwise - */ - static OFCondition copyElementToDataset(OFCondition &result, - DcmItem &dataset, - const DcmElement &delem, - const IODRule* rule); - - /** Add given element to the dataset - * The element is only added if 'result' is EC_Normal and the 'delem' - * pointer is not NULL. - * @param result Reference to status variable (checked before adding and - * updated afterwards!) - * @param dataset Reference to DICOM dataset to which the element should - * be added - * @param delem Pointer to DICOM element which should be added. The element - * is always consumed by this function, i.e.\ insertion was successful - * and therefore ownership is transferred to the dataset, or the - * element is deleted from memory if it could not be inserted. - * @param rule Rule describing parameters to be checked on element. - * @return Current value of 'result', EC_Normal if successful, an error code otherwise - */ - static OFCondition addElementToDataset(OFCondition &result, - DcmItem &dataset, - DcmElement *delem, - const IODRule* rule); - - /** Check element value for correct value multiplicity and type. - * @param delem Pointer to DICOM element to be checked (might be NULL) - * @param tagKey DICOM tag of the DICOM element the parameter 'delem' points to - * @param vm Value multiplicity (according to the data dictionary) to be checked for. - * (See DcmElement::checkVM() for a list of valid values.) - * Interpreted as cardinality (number of items) for sequence attributes. - * @param type Value type (valid value: "1", "1C", "2", something else) - * @param searchCond Optional flag indicating the status of a previous 'search' function call - * @param moduleName Optional module name to be printed (default: "IOD" if NULL) - * @param logLevel The log level to log errors to - * @return EC_Normal if element value is correct, error otherwise - */ - static OFCondition checkElementValue(const DcmElement *delem, - const DcmTagKey &tagKey, - const OFString &vm, - const OFString &type, - const OFCondition &searchCond = EC_Normal, - const char *moduleName = NULL, - const dcmtk::log4cplus::LogLevel logLevel = dcmtk::log4cplus::WARN_LOG_LEVEL); - - /** Check element value for correct value multiplicity and type. - * @param delem DICOM element to be checked - * @param vm Value multiplicity (according to the data dictionary) to be checked for. - * (See DcmElement::checkVM() for a list of valid values.) - * Interpreted as cardinality (number of items) for sequence attributes. - * @param type Value type (valid value: "1", "1C", "2", something else) - * @param searchCond Optional flag indicating the status of a previous 'search' function call - * @param moduleName Optional module name to be printed (default: "IOD" if NULL) - * @param logLevel The log level to log errors to - * @return EC_Normal if element value is correct, error otherwise - */ - static OFCondition checkElementValue(const DcmElement &delem, - const OFString &vm, - const OFString &type, - const OFCondition &searchCond = EC_Normal, - const char *moduleName = NULL, - const dcmtk::log4cplus::LogLevel logLevel = dcmtk::log4cplus::WARN_LOG_LEVEL); - - /** Get string value from element - * @param delem DICOM element from which the string value should be retrieved - * @param stringValue Reference to variable in which the result should be stored. - * (This parameter is automatically cleared if an error occurs.) - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getStringValueFromElement(const DcmElement &delem, - OFString &stringValue, - const signed long pos); - - /** Get string value from item - * @param key The tag key of the attribute whose value should be retrieved - * @param item The item to search the attribute in - * @param result Reference to variable in which the result should be stored. - * (This parameter is automatically cleared if an error occurs.) - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getStringValueFromItem(const DcmTagKey& key, - DcmItem& item, - OFString& result, - const signed long& pos); - - /** Get Float64 value from item - * @param key The tag key of the attribute whose value should be retrieved - * @param item The item to search the attribute in - * @param result Reference to variable in which the result should be stored. - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getFloat64ValueFromItem(const DcmTagKey& key, - DcmItem& item, - Float64& result, - const unsigned long& pos); - - /** Get Float64 values from item - * @param key The tag key of the attribute whose value should be retrieved - * @param item The item to search the attribute in - * @param result Reference to variable in which the result should be stored. - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getFloat64ValuesFromItem(const DcmTagKey& key, - DcmItem& item, - OFVector& result); - - /** Get Float64 value from element - * @param delem The element whose value should be retrieved - * @param result Reference to variable in which the result should be stored. - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getFloat64ValueFromElement(const DcmElement &delem, - Float64& result, - const unsigned long pos); - - /** Get Float64 values from element - * @param delem The element to get the value from - * @param result Reference to variable in which the result should be stored. - * @return EC_Normal if successful, an error code otherwise - */ - static OFCondition getFloat64ValuesFromElement(const DcmElement &delem, - OFVector& result); - - /** Set a DcmElement's content from Uint16 vector - * @param delem DICOM element to be filled - * @param values Vector use as a source for the values - * @param vm Value multiplicity (according to the data dictionary) to be - * checked for. (See DcmElement::checkVM() for a list of - * valid values.) - * @param check If OFTrue, then it is checked whether number of values - * conforms to the value provided by the vm parameter. - * @return Dtatus, EC_Normal if successful, an error code otherwise - */ - static OFCondition setUint16ValuesOnElement(DcmElement &delem, - const OFVector& values, - const OFString& vm, - const OFBool check); - - /** Get Uint16 values from DcmElement - * @param delem DICOM element to read from - * @param values Vector used as destination for the values - * @return Status EC_Normal if successful, an error code otherwise - */ - static OFCondition getUint16ValuesFromElement(DcmElement &delem, - OFVector& values); - - /** Returns single item from given sequence. Returns error number of items - * is 0 or more than 1. - * @param seq Sequence to read from. - * @param item The resulting item, NULL in case of error - * @param checkKey If given it is checked whether the given seq parameter - * matches the tag key provided in the checkKey parameter. If - * not, an error is returned. - * @return Status EC_Normal if successful, an error code otherwise - */ - static OFCondition getAndCheckSingleItem(DcmSequenceOfItems& seq, - DcmItem*& item, - const DcmTagKey& checkKey = DCM_UndefinedTagKey); - - /** Copies Uint8 values from given element to destination container - * (must support push_back() method). - * @param elem the element to read from. If NULL, an error is returned. - * @param destination the container to store the Uint8 values to - * @return EC_Normal if successful, an error code otherwise - */ - template - static OFCondition copyFromUint8Array(DcmElement* elem, - Container& destination) - { - if (elem == NULL) - return EC_IllegalParameter; - - size_t numValues = elem->getNumberOfValues(); - OFCondition result; - for (size_t count = 0; (count < numValues) && result.good(); count ++) - { - Uint8 value; - result = elem->getUint8(value, OFstatic_cast(unsigned long, count)); - if ( result.good() ) - { - destination.push_back(value); - } - } - if ( result.bad() ) + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * (be 'const'.) + * @param delem DICOM element used to store the value (always creates + * a copy of the dataset element's value) + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.) Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else + * which is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return EC_Normal if element could be retrieved and value is correct, + * an error code otherwise + */ + static OFCondition getAndCheckElementFromDataset( + DcmItem& dataset, DcmElement& delem, const OFString& vm, const OFString& type, const char* moduleName = NULL); + + /** Get element from dataset and check it for correct value multiplicity and + * type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const') + * @param tagKey Tag key of the element to get + * @param delem DICOM element that is set to a copy of the dataset's + * orinal element + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.) Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else + * which is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem& dataset, + const DcmTagKey& tagKey, + DcmElement*& delem, + const OFString& vm, + const OFString& type, + const char* moduleName = NULL); + + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const'.) + * @param delem DICOM element used to store the value (always creates + * a copy of the value from the original element) + * @param rule Rule describing parameters to be checked on element + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem& dataset, DcmElement& delem, const IODRule* rule); + + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const') + * @param delem DICOM element that is set to a copy of the dataset's + * orinal element + * @param rule Rule describing parameters to be checked on element. + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem& dataset, DcmElement*& delem, const IODRule* rule); + + /** Get current date in DICOM 'DA' format (YYYYMMDD) + * @param dateString String used to store the current date. + * (empty string if current date could not be retrieved) + * @return Resulting character string + */ + static const OFString& currentDate(OFString& dateString); + + /** Get current time in DICOM 'TM' format (HHMMSS) + * The optional UTC notation (e.g.\ +0100) is currently not supported. + * @param timeString String used to store the current time + * (empty string if current time could not be retrieved) + * @return Resulting character string, empty if time could not be retrieved + */ + static const OFString& currentTime(OFString& timeString); + + /** Copy given element to the dataset + * The element is only added if 'result' is EC_Normal. A copy of the given + * element is created, i.e.\ the caller is responsible for deleting the + * original element handed to this function (if desired). + * @param result Reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset Reference to DICOM dataset to which the element should + * be added + * @param delem Reference to DICOM element which should be added; a + * copy is created so caller is responsible for deleting delem (if + * desired). + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.). Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "2" or something else which + * is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return Current value of 'result', EC_Normal if successful, + * an error code otherwise + */ + static OFCondition copyElementToDataset(OFCondition& result, + DcmItem& dataset, + const DcmElement& delem, + const OFString& vm, + const OFString& type, + const char* moduleName = NULL); + + /** Copy given element to the dataset. The element is only added if 'result' + * is EC_Normal. + * @param result reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset reference to DICOM dataset to which the element + * should be added + * @param delem reference to DICOM element which should be added; the value + * is copied from the original dataset's element + * @param rule Rule describing parameters to be checked on element. + * @return Current value of 'result', EC_Normal if successful, an error code + * otherwise + */ + static OFCondition + copyElementToDataset(OFCondition& result, DcmItem& dataset, const DcmElement& delem, const IODRule* rule); + + /** Add given element to the dataset + * The element is only added if 'result' is EC_Normal and the 'delem' + * pointer is not NULL. + * @param result Reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset Reference to DICOM dataset to which the element should + * be added + * @param delem Pointer to DICOM element which should be added. The element + * is always consumed by this function, i.e.\ insertion was successful + * and therefore ownership is transferred to the dataset, or the + * element is deleted from memory if it could not be inserted. + * @param rule Rule describing parameters to be checked on element. + * @return Current value of 'result', EC_Normal if successful, an error code otherwise + */ + static OFCondition + addElementToDataset(OFCondition& result, DcmItem& dataset, DcmElement* delem, const IODRule* rule); + + /** Check element value for correct value multiplicity and type. + * @param delem Pointer to DICOM element to be checked (might be NULL) + * @param tagKey DICOM tag of the DICOM element the parameter 'delem' points to + * @param vm Value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Interpreted as cardinality (number of items) for sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else) + * @param searchCond Optional flag indicating the status of a previous 'search' function call + * @param moduleName Optional module name to be printed (default: "IOD" if NULL) + * @param logLevel The log level to log errors to + * @return EC_Normal if element value is correct, error otherwise + */ + static OFCondition checkElementValue(const DcmElement* delem, + const DcmTagKey& tagKey, + const OFString& vm, + const OFString& type, + const OFCondition& searchCond = EC_Normal, + const char* moduleName = NULL, + const dcmtk::log4cplus::LogLevel logLevel = dcmtk::log4cplus::WARN_LOG_LEVEL); + + /** Check element value for correct value multiplicity and type. + * @param delem DICOM element to be checked + * @param vm Value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Interpreted as cardinality (number of items) for sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else) + * @param searchCond Optional flag indicating the status of a previous 'search' function call + * @param moduleName Optional module name to be printed (default: "IOD" if NULL) + * @param logLevel The log level to log errors to + * @return EC_Normal if element value is correct, error otherwise + */ + static OFCondition checkElementValue(const DcmElement& delem, + const OFString& vm, + const OFString& type, + const OFCondition& searchCond = EC_Normal, + const char* moduleName = NULL, + const dcmtk::log4cplus::LogLevel logLevel = dcmtk::log4cplus::WARN_LOG_LEVEL); + + /** Get string value from element + * @param delem DICOM element from which the string value should be retrieved + * @param stringValue Reference to variable in which the result should be stored. + * (This parameter is automatically cleared if an error occurs.) + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getStringValueFromElement(const DcmElement& delem, OFString& stringValue, const signed long pos); + + /** Get string value from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * (This parameter is automatically cleared if an error occurs.) + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition + getStringValueFromItem(const DcmTagKey& key, DcmItem& item, OFString& result, const signed long& pos); + + /** Get Float64 value from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition + getFloat64ValueFromItem(const DcmTagKey& key, DcmItem& item, Float64& result, const unsigned long& pos); + + /** Get Float64 values from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValuesFromItem(const DcmTagKey& key, DcmItem& item, OFVector& result); + + /** Get Float64 value from element + * @param delem The element whose value should be retrieved + * @param result Reference to variable in which the result should be stored. + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValueFromElement(const DcmElement& delem, Float64& result, const unsigned long pos); + + /** Get Float64 values from element + * @param delem The element to get the value from + * @param result Reference to variable in which the result should be stored. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValuesFromElement(const DcmElement& delem, OFVector& result); + + /** Set a DcmElement's content from Float64 vector + * @param delem DICOM element to be filled + * @param values Vector use as a source for the values + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of + * valid values.) + * @param check If OFTrue, then it is checked whether number of values + * conforms to the value provided by the vm parameter. + * @return Dtatus, EC_Normal if successful, an error code otherwise + */ + static OFCondition setFloat64ValuesOnElement(DcmElement& delem, + const OFVector& values, + const OFString& vm, + const OFBool check); + + /** Get Float32 value from element + * @param delem The element whose value should be retrieved + * @param result Reference to variable in which the result should be stored. + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat32ValueFromElement(const DcmElement& delem, Float32& result, const unsigned long pos); + + /** Set a DcmElement's content from Float32 vector + * @param delem DICOM element to be filled + * @param values Vector use as a source for the values + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of + * valid values.) + * @param check If OFTrue, then it is checked whether number of values + * conforms to the value provided by the vm parameter. + * @return Dtatus, EC_Normal if successful, an error code otherwise + */ + static OFCondition setFloat32ValuesOnElement(DcmElement& delem, + const OFVector& values, + const OFString& vm, + const OFBool check); + + /** Set a DcmElement's content from Uint16 vector + * @param delem DICOM element to be filled + * @param values Vector use as a source for the values + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of + * valid values.) + * @param check If OFTrue, then it is checked whether number of values + * conforms to the value provided by the vm parameter. + * @return Dtatus, EC_Normal if successful, an error code otherwise + */ + static OFCondition + setUint16ValuesOnElement(DcmElement& delem, const OFVector& values, const OFString& vm, const OFBool check); + + /** Get Uint16 values from DcmElement + * @param delem DICOM element to read from + * @param values Vector used as destination for the values + * @return Status EC_Normal if successful, an error code otherwise + */ + static OFCondition getUint16ValuesFromElement(DcmElement& delem, OFVector& values); + + /** Returns single item from given sequence. Returns error number of items + * is 0 or more than 1. + * @param seq Sequence to read from. + * @param item The resulting item, NULL in case of error + * @param checkKey If given it is checked whether the given seq parameter + * matches the tag key provided in the checkKey parameter. If + * not, an error is returned. + * @return Status EC_Normal if successful, an error code otherwise + */ + static OFCondition + getAndCheckSingleItem(DcmSequenceOfItems& seq, DcmItem*& item, const DcmTagKey& checkKey = DCM_UndefinedTagKey); + + /** Copies Uint8 values from given element to destination container + * (must support push_back() method). + * @param elem the element to read from. If NULL, an error is returned. + * @param destination the container to store the Uint8 values to + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition copyFromUint8Array(DcmElement* elem, Container& destination) { - destination.clear(); - } - return result; - } - - /** Check whether SOP class UID matches the expected value - * @param item Item to read from. NULL value causes error return value. - * @param desiredSOPClass The value that is expected - * @param valueFound The value actually found (empty if no value could - * be retrieved) - * @return EC_Normal if value could be found and equals expected value, - * EC_TagNotFound if SOP Class UID is not found in dataset, - * EC_InvalidValue if SOP class differs from expected value. - */ - static OFCondition checkSOPClass(DcmItem* item, - const OFString& desiredSOPClass, - OFString& valueFound); - - /** Check whether given tag is a sequence tag - * @param key the tag key to be checked - * @param privateCreator The private creator to check for if tag is private - * @return OFTrue if given tag is a sequence tag, OFFalse otherwise - */ - static OFBool isSequenceTag(const DcmTagKey& key, - const OFString& privateCreator = ""); - - /** Reads items from DICOM sequence into container by creating a dedicated - * container item for each DICOM item. The container must support - * push_back(T) function and the container's element type T must support - * the read(DcmItem*) function. - * @param source The source sequence to read items from - * @param seqKey The sequence's tag key that is expected - * @param destination The destination container to read into - * @param cardinality Expected number of items. - * See DcmElement::checkVM() for a list of valid values. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. Used - * for error messages and can also be left empty. - * @return EC_Normal if successful, an error code otherwise - */ - template - static OFCondition readSubSequence(DcmSequenceOfItems* source, - const DcmTagKey& seqKey, - Container& destination, - const OFString& cardinality, - const OFString& type, - const OFString& module) - { - OFCondition result; - OFCondition exists = EC_Normal; - if (!source) - exists = EC_TagNotFound; - - /* Check sequence and report errors as warnings, read anyway */ - checkElementValue(source, seqKey, cardinality, type, exists, module.c_str()); - if (source) - { - DcmItem *item = OFstatic_cast(DcmItem*, source->nextInContainer(NULL)); - size_t count = 0; - while (item != NULL) - { - if (item != NULL) + if (elem == NULL) + return EC_IllegalParameter; + + size_t numValues = elem->getNumberOfValues(); + OFCondition result; + for (size_t count = 0; (count < numValues) && result.good(); count++) { - // define the element type - typedef typename OFremove_pointer::type Element; - Element *newElem = new Element(); - // read into container item (clears old data first) - if ( newElem != NULL) - { - result = (newElem)->read(*item, OFFalse /* no need to delete anything */); - if ( result.good() ) + Uint8 value; + result = elem->getUint8(value, OFstatic_cast(unsigned long, count)); + if (result.good()) { - destination.push_back(newElem); + destination.push_back(value); } - else + } + if (result.bad()) + { + destination.clear(); + } + return result; + } + + /** Check whether SOP class UID matches the expected value + * @param item Item to read from. NULL value causes error return value. + * @param desiredSOPClass The value that is expected + * @param valueFound The value actually found (empty if no value could + * be retrieved) + * @return EC_Normal if value could be found and equals expected value, + * EC_TagNotFound if SOP Class UID is not found in dataset, + * EC_InvalidValue if SOP class differs from expected value. + */ + static OFCondition checkSOPClass(DcmItem* item, const OFString& desiredSOPClass, OFString& valueFound); + + /** Check whether given tag is a sequence tag + * @param key the tag key to be checked + * @param privateCreator The private creator to check for if tag is private + * @return OFTrue if given tag is a sequence tag, OFFalse otherwise + */ + static OFBool isSequenceTag(const DcmTagKey& key, const OFString& privateCreator = ""); + + /** Reads items from DICOM sequence into container by creating a dedicated + * container item for each DICOM item. The container must support + * push_back(T) function and the container's element type T must support + * the read(DcmItem*) function. + * @param source The source sequence to read items from + * @param seqKey The sequence's tag key that is expected + * @param destination The destination container to read into + * @param cardinality Expected number of items. + * See DcmElement::checkVM() for a list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmSequenceOfItems* source, + const DcmTagKey& seqKey, + Container& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) + { + OFCondition result; + OFCondition exists = EC_Normal; + if (!source) + exists = EC_TagNotFound; + + /* Check sequence and report errors as warnings, read anyway */ + checkElementValue(source, seqKey, cardinality, type, exists, module.c_str()); + if (source) + { + DcmItem* item = OFstatic_cast(DcmItem*, source->nextInContainer(NULL)); + size_t count = 0; + while (item != NULL) { - delete newElem; - DCMIOD_WARN("Could not read item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (skipping item): " << result.text()); + if (item != NULL) + { + // define the element type + typedef typename OFremove_pointer::type Element; + Element* newElem = new Element(); + // read into container item (clears old data first) + if (newElem != NULL) + { + result = (newElem)->read(*item, OFFalse /* no need to delete anything */); + if (result.good()) + { + destination.push_back(newElem); + } + else + { + delete newElem; + DCMIOD_WARN("Could not read item #" << count << " from " + << DcmTag(source->getTag()).getTagName() + << " (skipping item): " << result.text()); + } + } + else + { + DCMIOD_ERROR("Could not store data from item #" << count << " from " + << DcmTag(source->getTag()).getTagName() + << " (skipping item): Memory exhausted?"); + } + } + else + { + DCMIOD_WARN("Could not get item #" << count << " from " << DcmTag(source->getTag()).getTagName() + << " (malformed data or internal error), skipping item"); + } + item = OFstatic_cast(DcmItem*, source->nextInContainer(item)); + count++; } - } - else - { - DCMIOD_ERROR("Could not store data from item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (skipping item): Memory exhausted?"); - } } else { - DCMIOD_WARN("Could not get item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (malformed data or internal error), skipping item"); + result = EC_IllegalParameter; } - item = OFstatic_cast(DcmItem*, source->nextInContainer(item)); - count++; - } + return result; } - else + + /** Reads DICOM sequence into container by creating a dedicated container element + * for each DICOM item. The container must support push_back(T) function + * and the container's element type T must support the read(DcmItem*) function. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param cardinality Expected number of items. + * See DcmElement::checkVM() for a list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + * @return status EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmItem& source, + const DcmTagKey& seqKey, + Container& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) { - result = EC_IllegalParameter; + OFCondition result; + DcmSequenceOfItems* seq = NULL; + + /* Get sequence and read it */ + source.findAndGetSequence(seqKey, seq); + result = readSubSequence(seq, seqKey, destination, cardinality, type, module); + return result; } - return result; - } - - - /** Reads DICOM sequence into container by creating a dedicated container element - * for each DICOM item. The container must support push_back(T) function - * and the container's element type T must support the read(DcmItem*) function. - * @param source The source DICOM item read the sequence from - * @param seqKey The tag key of the sequence to be read - * @param destination The destination container to read into - * @param cardinality Expected number of items. - * See DcmElement::checkVM() for a list of valid values. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. Used - * for error messages and can also be left empty. - * @return status EC_Normal if successful, an error code otherwise - */ - template - static OFCondition readSubSequence(DcmItem& source, - const DcmTagKey& seqKey, - Container& destination, - const OFString& cardinality, - const OFString& type, - const OFString& module) - { - OFCondition result; - DcmSequenceOfItems *seq = NULL; - - /* Get sequence and read it */ - source.findAndGetSequence(seqKey, seq); - result = readSubSequence(seq, seqKey, destination, cardinality, type, module ); - return result; - } - - - /** Reads DICOM sequence into container by creating a dedicated container - * element for each DICOM item. The container must support the - * push_back(T) function and the container's element type T must support - * the read(DcmItem*) function. - * @param source The source DICOM item read the sequence from - * @param seqKey The tag key of the sequence to be read - * @param destination The destination container to read into - * @param rule The rule for reading this sequence. If NULL, an error is returned. - * @return EC_Normal if successful, an error code otherwise - */ - template - static OFCondition readSubSequence(DcmItem& source, - const DcmTagKey& seqKey, - Container& destination, - IODRule *rule) - { - if (rule == NULL) + + /** Reads DICOM sequence into container by creating a dedicated container + * element for each DICOM item. The container must support the + * push_back(T) function and the container's element type T must support + * the read(DcmItem*) function. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param rule The rule for reading this sequence. If NULL, an error is returned. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmItem& source, const DcmTagKey& seqKey, Container& destination, IODRule* rule) { - DCMIOD_ERROR("Cannot read sequence " << seqKey << " (no rule supplied)"); - return IOD_EC_NoSuchRule; + if (rule == NULL) + { + DCMIOD_ERROR("Cannot read sequence " << seqKey << " (no rule supplied)"); + return IOD_EC_NoSuchRule; + } + return readSubSequence( + source, seqKey, destination, rule->getVM(), rule->getType(), rule->getModule()); } - return readSubSequence(source, seqKey, destination, rule->getVM(), rule->getType(), rule->getModule()); - } - - - /** Reads single DICOM item from a specific sequence into a destination class. - * The container must support the read(DcmItem) function. If a single item - * (i.e.\ the first item of the specified sequence) cannot be read, an error - * is returned. - * @param source The source DICOM item read the sequence from - * @param seqKey The tag key of the sequence to be read - * @param destination The destination container to read into - * See DcmElement::checkVM() for a list of valid values. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. - * Used for error messages and can also be left empty. - * @return EC_Normal if successful, an error code otherwise - */ - template - static OFCondition readSingleItem(DcmItem& source, - const DcmTagKey& seqKey, - Container& destination, - const OFString& type, - const OFString& module) - { - OFCondition result; - /* Check sequence, reports cardinality and type errors as warnings */ - checkSubSequence(result, source, seqKey, "1", type, module, dcmtk::log4cplus::WARN_LOG_LEVEL); - - /* Try to read sequence into internal data (ignore errors as much as possible) */ - DcmItem* item = NULL; - result = source.findAndGetSequenceItem(seqKey, item, 0); - if (item != NULL) + + /** Reads single DICOM item from a specific sequence into a destination class. + * The container must support the read(DcmItem) function. If a single item + * (i.e.\ the first item of the specified sequence) cannot be read, an error + * is returned. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSingleItem( + DcmItem& source, const DcmTagKey& seqKey, Container& destination, const OFString& type, const OFString& module) { - // read into Container (clears old data first) - result = destination.read(*item, OFTrue /* clear old data */); + OFCondition result; + /* Check sequence, reports cardinality and type errors as warnings */ + checkSubSequence(result, source, seqKey, "1", type, module, dcmtk::log4cplus::WARN_LOG_LEVEL); + + /* Try to read sequence into internal data (ignore errors as much as possible) */ + DcmItem* item = NULL; + result = source.findAndGetSequenceItem(seqKey, item, 0); + if (item != NULL) + { + // read into Container (clears old data first) + result = destination.read(*item, OFTrue /* clear old data */); + } + return result; } - return result; - } - - /** Reads single DICOM item from a specific sequence into a destination class. - * The container must support the read(DcmItem) function. If a single item - * (i.e.\ the first item of the specified sequence) cannot be read, an error - * is returned. - * @param source The source DICOM item read the sequence from - * @param seqKey The tag key of the sequence to be read - * @param destination The destination container to read into - * See DcmElement::checkVM() for a list of valid values. - * @param rule The rule (for the sequence) used for reading. - * @return EC_Normal if successful, an error code otherwise. If the rule - * equlas NULL, then nothing is read at all and an error is returned - * (IOD_EC_NoSuchRule), but no error is reported to the logger. - */ - template - static OFCondition readSingleItem(DcmItem& source, - const DcmTagKey& seqKey, - Container& destination, - IODRule *rule = NULL) - { - if (rule == NULL) + + /** Reads single DICOM item from a specific sequence into a destination class. + * The container must support the read(DcmItem) function. If a single item + * (i.e.\ the first item of the specified sequence) cannot be read, an error + * is returned. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param rule The rule (for the sequence) used for reading. + * @return EC_Normal if successful, an error code otherwise. If the rule + * equlas NULL, then nothing is read at all and an error is returned + * (IOD_EC_NoSuchRule), but no error is reported to the logger. + */ + template + static OFCondition + readSingleItem(DcmItem& source, const DcmTagKey& seqKey, Container& destination, IODRule* rule = NULL) { - DCMIOD_DEBUG("Will not read sequence " << seqKey << ": No rule supplied"); - return IOD_EC_NoSuchRule; + if (rule == NULL) + { + DCMIOD_DEBUG("Will not read sequence " << seqKey << ": No rule supplied"); + return IOD_EC_NoSuchRule; + } + + return readSingleItem(source, seqKey, destination, rule->getType(), rule->getModule()); } - return readSingleItem(source, seqKey, destination, rule->getType(), rule->getModule()); - } - - /** Write given container into a DICOM sequence that is created within the - * given item. The sequence is created from scratch, i.e.\ any old sequence - * (and its items) will be overwritten. - * @param result If writing is successful, result will contain EC_Normal. - * Otherwise an error code is set. - * @param seqKey The tag key of the sequence to be write - * @param source The source container to read from. Must support the - * write(DcmItem*) function. - * @param destination The DICOM destination item to write the sequence to - * See DcmElement::checkVM() for a list of valid values. - * @param cardinality Expected number of items (i.e.\ expected number of - * elements in source container). See DcmElement::checkVM() for a - * list of valid values. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. Used - * for error messages and can also be left empty. - */ - template - static void writeSubSequence(OFCondition& result, - const DcmTagKey& seqKey, - Container& source, - DcmItem& destination, - const OFString& cardinality, - const OFString& type, - const OFString& module) - { - if ( result.good() ) + /** Write given container into a DICOM sequence that is created within the + * given item. The sequence is created from scratch, i.e.\ any old sequence + * (and its items) will be overwritten. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be write + * @param source The source container to read from. Must support the + * write(DcmItem*) function. + * @param destination The DICOM destination item to write the sequence to + * @param cardinality Expected number of items (i.e.\ expected number of + * elements in source container). See DcmElement::checkVM() for a + * list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + */ + template + static void writeSubSequence(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) { - // Delete old data - destination.findAndDeleteElement(seqKey); - - // If we have meaningful data, write it - OFBool haveData = source.size() > 0; - if (haveData) - { - destination.insertEmptyElement(seqKey); - Uint32 count = 0; - typename Container::iterator it = source.begin(); - while ( it != source.end() && result.good() ) + if (result.good()) { - if ( (*it) != NULL) - { - DcmItem *localItem = NULL; - // If item is NULL result.bad() is always true. - result = destination.findOrCreateSequenceItem(seqKey, localItem, -2 /* append new */); - if ( result.good() ) + // Delete old data + destination.findAndDeleteElement(seqKey); + + // If we have meaningful data, write it + OFBool haveData = source.size() > 0; + if (haveData) { - result = (*it)->write(*localItem); - if ( result.bad() ) - { - destination.findAndDeleteSequenceItem(seqKey, -1 /* last */); - DCMIOD_ERROR("Could not write item #" << count << " in " << DcmTag(seqKey).getTagName() << ": " << result.text()); - } + destination.insertEmptyElement(seqKey); + Uint32 count = 0; + typename Container::iterator it = source.begin(); + while (it != source.end() && result.good()) + { + if ((*it) != NULL) + { + DcmItem* localItem = NULL; + // If item is NULL result.bad() is always true. + result = destination.findOrCreateSequenceItem(seqKey, localItem, -2 /* append new */); + if (result.good()) + { + result = (*it)->write(*localItem); + if (result.bad()) + { + destination.findAndDeleteSequenceItem(seqKey, -1 /* last */); + DCMIOD_ERROR("Could not write item #" << count << " in " << DcmTag(seqKey).getTagName() + << ": " << result.text()); + } + } + else + { + DCMIOD_ERROR("Could not insert item data #" << count << " of " + << DcmTag(seqKey).getTagName() + << " (internal error), ignoring"); + } + } + else + { + DCMIOD_ERROR("Found uninitialized container item (NULL value) for sequence " + << DcmTag(seqKey).getTagName() << " (internal error, skipping)"); + } + count++; + it++; + } } - else + // If we do not have data, create empty sequence if type 2 + else if (type == "2") + { + destination.insertEmptyElement(seqKey); + } + + // Check result + checkSubSequence(result, destination, seqKey, cardinality, type, module, dcmtk::log4cplus::ERROR_LOG_LEVEL); + + // Clean up if we did not have success */ + if (result.bad()) { - DCMIOD_ERROR("Could not insert item data #" << count << " of " << DcmTag(seqKey).getTagName() << " (internal error), ignoring"); + destination.findAndDeleteElement(seqKey); } - } - else - { - DCMIOD_ERROR("Found uninitialized container item (NULL value) for sequence " << DcmTag(seqKey).getTagName() << " (internal error, skipping)"); - } - count++; - it++; } - } - // If we do not have data, create empty sequence if type 2 - else if (type == "2") - { - destination.insertEmptyElement(seqKey); - } - - // Check result - checkSubSequence(result, destination, seqKey, cardinality, type, module, dcmtk::log4cplus::ERROR_LOG_LEVEL); - - // Clean up if we did not have success */ - if (result.bad()) - { - destination.findAndDeleteElement(seqKey); - } } - } - - /** Write given container into a DICOM sequence that is created within the given item. - * The container. The sequence is created from scratch, i.e.\ any old sequence - * (and its items) will be overwritten. - * @param result If writing is successful, result will contain EC_Normal. Otherwise - * an error code is set. - * @param seqKey The tag key of the sequence to be write - * @param source The source container to read from. Must support the write(DcmItem*) - * function. - * @param destination The DICOM destination item to write the sequence to - * @param rule Rule describing the requirements for this sequence. If NULL - * an error is returned (IOD_EC_NoSuchRule), but no error error is reported - * to the logger. - */ - template - static void writeSubSequence(OFCondition& result, - const DcmTagKey& seqKey, - Container& source, - DcmItem& destination, - IODRule* rule) - { - if ( result.good() ) + + /** Write given container into a DICOM sequence that is created within the given item. + * The container. The sequence is created from scratch, i.e.\ any old sequence + * (and its items) will be overwritten. + * @param result If writing is successful, result will contain EC_Normal. Otherwise + * an error code is set. + * @param seqKey The tag key of the sequence to be write + * @param source The source container to read from. Must support the write(DcmItem*) + * function. + * @param destination The DICOM destination item to write the sequence to + * @param rule Rule describing the requirements for this sequence. If NULL + * an error is returned (IOD_EC_NoSuchRule), but no error error is reported + * to the logger. + */ + template + static void writeSubSequence( + OFCondition& result, const DcmTagKey& seqKey, Container& source, DcmItem& destination, IODRule* rule) { - if (rule == NULL) - { - DCMIOD_DEBUG("Will not write sequence " << seqKey << ": No rule supplied"); - result = IOD_EC_NoSuchRule; - } - else - { - writeSubSequence(result, rule->getTagKey(), source, destination, rule->getVM(), rule->getType(), rule->getModule()); - } + if (result.good()) + { + if (rule == NULL) + { + DCMIOD_DEBUG("Will not write sequence " << seqKey << ": No rule supplied"); + result = IOD_EC_NoSuchRule; + } + else + { + writeSubSequence( + result, rule->getTagKey(), source, destination, rule->getVM(), rule->getType(), rule->getModule()); + } + } } - } - - - /** Writes given container into a DICOM item of a specific sequence. The - * sequence is created from scratch so that any old information will be lost. - * @param result If writing is successful, result will contain EC_Normal. - * Otherwise an error code is set. - * @param seqKey The tag key of the sequence to be written - * @param source The source container to read from. Must support the write(DcmItem*) - * function. - * @param destination The DICOM item that should hold the sequence - * (with a single item) in the end. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. - * Used for error messages and can also be left empty. - */ - template - static void writeSingleItem(OFCondition& result, - const DcmTagKey& seqKey, - Container& source, - DcmItem& destination, - const OFString& type, - const OFString& module) - { - if ( result.good() ) + + /** Writes given container into a DICOM item of a specific sequence. The + * sequence is created from scratch so that any old information will be lost. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be written + * @param source The source container to read from. Must support the write(DcmItem*) + * function. + * @param destination The DICOM item that should hold the sequence + * (with a single item) in the end. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + */ + template + static void writeSingleItem(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + const OFString& type, + const OFString& module) { - // Delete old data - destination.findAndDeleteElement(seqKey); - - /* If we have data, write it */ - OFCondition haveData = source.check(OFTrue /* Be quiet */); - if (haveData.good()) - { - DcmItem *localItem = NULL; - // If item is NULL result.bad() is always true. - result = destination.findOrCreateSequenceItem(seqKey, localItem, 0); - if ( result.good() ) + if (result.good()) { - result = source.write(*localItem); - // It can happen that check() returns OK but no elements have to be - // written at all (e.g.\ if it contains only type 3 attributes). In that - // case a sequence with a single empty item is written which must be removed - // afterwards. - if (result.good() && (localItem->card() == 0) ) - { + // Delete old data destination.findAndDeleteElement(seqKey); - } + + /* If we have data, write it */ + OFCondition haveData = source.check(OFTrue /* Be quiet */); + if (haveData.good()) + { + DcmItem* localItem = NULL; + // If item is NULL result.bad() is always true. + result = destination.findOrCreateSequenceItem(seqKey, localItem, 0); + if (result.good()) + { + result = source.write(*localItem); + // It can happen that check() returns OK but no elements have to be + // written at all (e.g.\ if it contains only type 3 attributes). In that + // case a sequence with a single empty item is written which must be removed + // afterwards. + if (result.good() && (localItem->card() == 0)) + { + destination.findAndDeleteElement(seqKey); + } + } + } + /* If we do not have data, insert empty for type 2 */ + else if (type == "2") + { + destination.insertEmptyElement(seqKey); + } + else if (type == "1C") + { + DCMIOD_TRACE("Skipping type 1C sequence " << seqKey << ": No data or incomplete data available"); + } + else if (type == "3") + { + DCMIOD_TRACE("Skipping type 3 sequence " << seqKey << ": No data or incomplete data available"); + } + /* Check outcome */ + checkSubSequence(result, destination, seqKey, "1", type, module, dcmtk::log4cplus::ERROR_LOG_LEVEL); } - } - /* If we do not have data, insert empty for type 2 */ - else if (type == "2") - { - destination.insertEmptyElement(seqKey); - } - else if (type == "1C") - { - DCMIOD_TRACE("Skipping type 1C sequence " << seqKey << ": No data or incomplete data available"); - } - else if (type == "3") - { - DCMIOD_TRACE("Skipping type 3 sequence " << seqKey << ": No data or incomplete data available"); - } - /* Check outcome */ - checkSubSequence(result, destination, seqKey, "1", type, module, dcmtk::log4cplus::ERROR_LOG_LEVEL); } - } - - /** Writes given container into a DICOM item of a specific sequence. - * The sequence is created from scratch so that any old information - * will be lost. - * @param result If writing is successful, result will contain EC_Normal. - * Otherwise an error code is set. - * @param seqKey The tag key of the sequence to be written - * @param source The source container to read from. Must support the - * write(DcmItem*) function. - * @param destination The DICOM item that should hold the sequence - * (with a single item) in the end. - * @param rule The rule for writing the given sequence - */ - template - static void writeSingleItem(OFCondition& result, - const DcmTagKey& seqKey, - Container& source, - DcmItem& destination, - IODRule *rule) - { - if (result.good()) + + /** Writes given container into a DICOM item of a specific sequence. + * The sequence is created from scratch so that any old information + * will be lost. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be written + * @param source The source container to read from. Must support the + * write(DcmItem*) function. + * @param destination The DICOM item that should hold the sequence + * (with a single item) in the end. + * @param rule The rule for writing the given sequence + */ + template + static void writeSingleItem( + OFCondition& result, const DcmTagKey& seqKey, Container& source, DcmItem& destination, IODRule* rule) { - if (rule == NULL) - { - DCMIOD_ERROR("Cannot write sequence " << seqKey << " (no rule supplied)"); - result = EC_CannotCheck; - } - else - { - writeSingleItem(result, seqKey, source, destination, rule->getType(), rule->getModule()); - } + if (result.good()) + { + if (rule == NULL) + { + DCMIOD_ERROR("Cannot write sequence " << seqKey << " (no rule supplied)"); + result = EC_CannotCheck; + } + else + { + writeSingleItem(result, seqKey, source, destination, rule->getType(), rule->getModule()); + } + } } - } - - - /** Check whether a given sequence exists in a given item and whether it conforms to - * to its requirement type - * @param result If sequence is valid, result is set to EC_Normal, otherwise - * to an error. - * @param surroundingItem The item that should contain the given sequence. - * @param seqKey The sequence to look for - * @param cardinality Expected number of items (i.e.\ expected number of - * elements in source container). See DcmElement::checkVM() for a - * list of valid values. - * @param type The sequence type as noted in part 3 of the DICOM standard, - * i.e.\ "1,1C,2,2C or 3". - * @param module Name of the module/macro this sequence is contained in. - * Used for error messages and can also be left empty. - * @param logLevel The log level to write errors to - */ - static void checkSubSequence(OFCondition& result, - DcmItem& surroundingItem, - const DcmTagKey& seqKey, - const OFString& cardinality, - const OFString& type, - const OFString& module, - const dcmtk::log4cplus::LogLevel logLevel); - - /** Deletes all elements from given container and calls "delete" on each - * of them to clear memory. - * @param container The container that should be cleared. Must contain - * pointers to objects that are allocated on the heap. - */ - template - static void freeContainer(Container& container) - { - typename Container::iterator it = container.begin(); - while (it != container.end()) + + /** Check whether a given sequence exists in a given item and whether it conforms to + * to its requirement type + * @param result If sequence is valid, result is set to EC_Normal, otherwise + * to an error. + * @param surroundingItem The item that should contain the given sequence. + * @param seqKey The sequence to look for + * @param cardinality Expected number of items (i.e.\ expected number of + * elements in source container). See DcmElement::checkVM() for a + * list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + * @param logLevel The log level to write errors to + */ + static void checkSubSequence(OFCondition& result, + DcmItem& surroundingItem, + const DcmTagKey& seqKey, + const OFString& cardinality, + const OFString& type, + const OFString& module, + const dcmtk::log4cplus::LogLevel logLevel); + + /** Deletes all elements from given container and calls "delete" on each + * of them to clear memory. + * @param container The container that should be cleared. Must contain + * pointers to objects that are allocated on the heap. + */ + template + static void freeContainer(Container& container) { - delete *it; - it++; + typename Container::iterator it = container.begin(); + while (it != container.end()) + { + delete *it; + it++; + } + container.clear(); } - container.clear(); - } - - /** Clones and copies all elements from source to destination container by - * copy constructing all elements. - * @param src The container that should be copied. Must contain pointers - * to objects that are allocated on the heap, and that are - * copy-constructible - * @param dst The container to copy the cloned elements to. - */ - template - static void copyContainer(const Container& src, Container& dst) - { - typedef typename OFremove_pointer::type Element; - typename Container::const_iterator it = src.begin(); - while (it != src.end()) + + /** Clones and copies all elements from source to destination container by + * copy constructing all elements. + * If copying fails (because memory is exhausted), EC_MemoryExhausted is returned + * and the destination container is returned empty, i.e. all temporary copies + * of its elements are freed and removed from the container. + * @param src The container that should be copied. Must contain pointers + * to objects that are allocated on the heap, and that are + * copy-constructible + * @param dst The container to copy the cloned elements to. + * @return EC_Normal if successful, error otherwise + */ + template + static OFCondition copyContainer(const Container& src, Container& dst) { - if (*it != NULL) - { - Element *elem = new Element(**it); - dst.push_back ( elem ); - } - else - { - DCMIOD_ERROR("Could not copy element while copying container: Element is NULL, skipping"); - } - it++; + typedef typename OFremove_pointer::type Element; + typename Container::const_iterator it = src.begin(); + while (it != src.end()) + { + if (*it != NULL) + { + Element* elem = new Element(**it); + if (elem == NULL) + { + freeContainer(dst); + return EC_MemoryExhausted; + } + dst.push_back(elem); + } + else + { + DCMIOD_ERROR("Could not copy element while copying container: Element in source is NULL, skipping"); + } + it++; + } + return EC_Normal; } - } - - - template - static OFCondition setContentDateAndTimeNow(ModuleType& module) - { - OFDate date; - date.setCurrentDate(); - OFString tempstr; - date.getISOFormattedDate(tempstr, OFFalse /* no delimiters */); - OFCondition result = module.setContentDate(tempstr); - if (result.good()) + + /** Compares all elements in source and destination container by + * using their respective compare(const Container& rhs) method. + * If the number or elements in the Containers are different, the + * containers are not considered equal. + * @param src The first container + * @param dst The second container + * @return Zero if containers are equal, other number otherwise + */ + template + static int compareContainer(const Container& src, const Container& dst) { - OFTime time; - time.setCurrentTime(); - time.getISOFormattedTime(tempstr, OFTrue /* include seconds */, OFFalse, OFFalse, OFFalse); - result = module.setContentTime(tempstr); + size_t card = src.size(); + if (card != dst.size()) + return -1; + typename Container::const_iterator it = src.begin(); + typename Container::const_iterator it2 = dst.begin(); + while (it != src.end()) + { + if ((*it)->compare(**it2) != 0) + return 1; + it++; + it2++; + } + return 0; } - return result; - } - - - /** Function that takes a string representation of a tag key and - * converts it to a tag key instance if possible - * @param keyString String of the format "(gggg,eeee)" - * @return The tag key if it could be parsed, DCM_UndefinedTagKey is returned - * instead (0xffff,0xffff) - */ - static const DcmTagKey parseTagKey(const OFString& keyString); - - /** Decompress given dataset if possible. Decompression codecs have to be - * registered beforehand. - * @param dset The dataset to decompress - * @return EC_Normal if decompression works, error otherwise - */ - static OFCondition decompress(DcmDataset& dset); - - /** Create new Unique Identifier (UID) - * @param level 0: instance level, 1: Series level, >=2: Study level. - * Calling always with level=0 is not an error but will result - * in unique values, too. - * @return The UID created. - */ - static OFString createUID(const Uint8 level = 0); - - /** Print warning if more than 2147483647 frames are present. This is the maximum - * number since the Number of Frames attribute has a VR of IS which allows - * a maximum of 2^31-1. - * The method returns the number of frames that can be used, i.e. either - * 2147483647 if the maximum is exceeded, otherwise the actual number - * of frames. - * @param numFramesPresent The number of frames actually present - * @param warning The message to be printed if Number of Frames - * is larger than 2147483647. - * @return Number of frames that can be safely used. - */ - static Uint32 limitMaxFrames(const size_t numFramesPresent, - const OFString& warning); -private: + template + static OFCondition setContentDateAndTimeNow(ModuleType& module) + { + OFDate date; + date.setCurrentDate(); + OFString tempstr; + date.getISOFormattedDate(tempstr, OFFalse /* no delimiters */); + OFCondition result = module.setContentDate(tempstr); + if (result.good()) + { + OFTime time; + time.setCurrentTime(); + time.getISOFormattedTime(tempstr, OFTrue /* include seconds */, OFFalse, OFFalse, OFFalse); + result = module.setContentTime(tempstr); + } + return result; + } - // We only have static functions so we do not need an instance of - // this class so far. + /** Function that takes a string representation of a tag key and + * converts it to a tag key instance if possible + * @param keyString String of the format "(gggg,eeee)" + * @return The tag key if it could be parsed, DCM_UndefinedTagKey is returned + * instead (0xffff,0xffff) + */ + static const DcmTagKey parseTagKey(const OFString& keyString); + + /** Decompress given dataset if possible. Decompression codecs have to be + * registered beforehand. + * @param dset The dataset to decompress + * @return EC_Normal if decompression works, error otherwise + */ + static OFCondition decompress(DcmDataset& dset); + + /** Create new Unique Identifier (UID) + * @param level 0: instance level, 1: Series level, >=2: Study level. + * Calling always with level=0 is not an error but will result + * in unique values, too. + * @return The UID created. + */ + static OFString createUID(const Uint8 level = 0); + + /** Print warning if more than 2147483647 frames are present. This is the maximum + * number since the Number of Frames attribute has a VR of IS which allows + * a maximum of 2^31-1. + * The method returns the number of frames that can be used, i.e. either + * 2147483647 if the maximum is exceeded, otherwise the actual number + * of frames. + * @param numFramesPresent The number of frames actually present + * @param warning The message to be printed if Number of Frames + * is larger than 2147483647. + * @return Number of frames that can be safely used. + */ + static Uint32 limitMaxFrames(const size_t numFramesPresent, const OFString& warning); + + /** Extracts Frame structures from the given pixel data element. Only + * applicable for pixel data with Bits Allocated = 1. Within the pixel data element, all + * frames are packed next to each other, with the end of one frame and the + * beginning of the next frame packed bit by bit next to each other. The + * resulting Frames are a bit-by-bit copy of their original counterpart. + * However, their first bit is aligned to the first bit/byte in the Frame, + * and the unused bits in the last byte (if any) are zeroed out. + * @param pixData The pixel data to read from + * @param numFrames The number of frames to read + * @param bitsPerFrame The number of bits per frame (usually rows * columns) + * @param results The resulting frames. Memory for the frames is allocated + * by the method, so the Vector can/should be empty before calling. + * @result Return EC_Normal on success, error otherwise + */ + static OFCondition extractBinaryFrames(Uint8* pixData, + const size_t numFrames, + const size_t bitsPerFrame, + OFVector& results); + + /** Aligns 1 bit per pixel frame data starting at a given bit position in the + * provided buffer with the start of that buffer. This is used to create + * a frame structure where all the bytes (including the first one) only + * contain data from the frame at hand. + * Note that each byte is filled from the right, i.e. the first pixel will + * represented by the bit at the very right of the first byte, and the 9th + * pixel will be in the very right position of the following byte. + * Example: + * 3 bytes input buffer: edcbaZYX mlkjihgf utsrqpon + * Result after aligning 3 bits: fghedcba ponmlkji 000utsrq + * The 000 are unused bits and therefore zeroed out in the last byte. Bits + * ZYX will be shifted out which is ok since it does not belong to the + * current frame. See also dcmseg/tests/tutils.cc for more examples. + * @param buf The address of the memory buffer to shift + * @param bufLen The length of the buf memory block in bytes + * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. + */ + static void alignFrameOnByteBoundary(Uint8* buf, const size_t bufLen, const Uint8 numBits); + +private: + // We only have static functions so we do not need an instance of + // this class so far. - /** Undefined default constructor (only static functions) - */ - DcmIODUtil(); + /** Undefined default constructor (only static functions) + */ + DcmIODUtil(); - /** Undefined destructor - */ - ~DcmIODUtil(); + /** Undefined destructor + */ + ~DcmIODUtil(); }; #endif // IODUTIL_H diff --git a/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h b/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h index 77a34e1d..02d59f6f 100644 --- a/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h +++ b/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -28,47 +28,44 @@ #include "dcmtk/dcmiod/modbase.h" /** Class representing the Acquisition Context Module. At the moment - * only an empty Acquisition Context Sequence is supported, so this - * class servers more as a placeholder at the moment. - * - * Acquisition Context Sequence: (SQ, 1-n, 2) - * - */ + * only an empty Acquisition Context Sequence is supported, so this + * class servers more as a placeholder at the moment. + * + * Acquisition Context Sequence: (SQ, 1-n, 2) + * + */ class DCMTK_DCMIOD_EXPORT IODAcquisitionContextModule : public IODModule { public: + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + IODAcquisitionContextModule(OFshared_ptr item, OFshared_ptr rules); - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set where this classes rules are added to. If NULL, the - * class creates an empty rule set. - */ - IODAcquisitionContextModule(OFshared_ptr item, - OFshared_ptr rules); + /** Constructor + */ + IODAcquisitionContextModule(); - /** Constructor - */ - IODAcquisitionContextModule(); + /** Destructor + */ + virtual ~IODAcquisitionContextModule(); - /** Destructor - */ - virtual ~IODAcquisitionContextModule(); + /** Resets rules to their original values + */ + virtual void resetRules(); - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("AcquisitionContextModule") - * @return Name of the module ("AcquisitionContextModule") - */ - virtual OFString getName() const; + /** Get name of module ("AcquisitionContextModule") + * @return Name of the module ("AcquisitionContextModule") + */ + virtual OFString getName() const; private: - - /// The name of this module ("AcquisitionContextModule") - static const OFString m_ModuleName; + /// The name of this module ("AcquisitionContextModule") + static const OFString m_ModuleName; }; #endif // MODACQUISITIONCONTEXT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modbase.h b/dcmiod/include/dcmtk/dcmiod/modbase.h index 2270c177..36d49b44 100644 --- a/dcmiod/include/dcmtk/dcmiod/modbase.h +++ b/dcmiod/include/dcmtk/dcmiod/modbase.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,11 +23,11 @@ #define MODBASE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofvector.h" #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmiod/ioddef.h" #include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" /** Class for managing sets of dicom attributes (e.g.\ macros and modules). * The data is hold in a container (DcmItem) that can be shared with other @@ -48,166 +48,153 @@ class DCMTK_DCMIOD_EXPORT IODComponent { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * an empty rule set. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - IODComponent(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor, creates rules and item from scratch. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - IODComponent(IODComponent* parent = NULL); - - /** Assignment operator, copies contained item and rule set from rhs to - * "this" attribute set. Performs deep copy, i.e.\ the contained item - * and the rule set are copied. The parent component is set to NULL. - * @param rhs The IODComponent to be assigned - * @return Reference to this module - */ - IODComponent& operator=(const IODComponent& rhs); - - /** Copy constructor, copies reference to contained item and - * rule set to "this" attribute set. - * @param rhs The component to be assigned - */ - IODComponent(const IODComponent& rhs); - - /** Virtual Destructor - */ - virtual ~IODComponent(); - - /** Clear all attributes from the data that are handled by this module. - * An attribute is considered belonging to the module if there are rules - * marked as belonging to this module via the rule's module name. - */ - void clearData(); - - /** Set missing values by inventing "default values". Automatically - * called during write() in IODComponent; does nothing in this base - * class implementation but can be overwritten by derived classes if - * default values are desired. - */ - virtual void inventMissing(); - - /** Resets rules to their original values - */ - virtual void resetRules() =0; - - /** Get rules handled by this module - * @return The rules - */ - OFshared_ptr getRules() - { - return m_Rules; - } - - /** Make component optional by turning all attributes requirement types of it - * to type 3. In order to reset to the attribute's original types, - * resetRules() can be used. - */ - virtual void makeOptional(); - - /** Get name of component - * @return Name of the module - */ - virtual OFString getName() const =0; - - /** Get the data handled by this module - * @return The item containing the data of this module - */ - DcmItem& getData() - { - return *m_Item; - } - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Check whether this component's data satisfies the underlying - * rules - * @param quiet If OFTrue, not error / warning messages will be produced. Only - * the returned error code will indicate error or OK. Per default, - * logging output is produced (OFFalse). - * @result EC_Normal if rules are satisfied, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Comparison operator for IOD Components - * @param rhs The right hand side of the comparison - * @return 0, if the given object is equal to this object, other value otherwise - */ - virtual int compare(const IODComponent& rhs) const; - - /** Static helper function that reads attributes from given - * item into destination item, as determined by the provided - * rules and component name. The rules are only applied when reading - * from the source (which may result in warning messages on the logger), - * but if they could be found they are taken over into the destination - * item no matter whether the element validates against the rule. - * @param source The item to read from - * @param rules The rules that provide the attributes and requirements - * for these attributes - * @param destination The destination to write to - * @param componentName The name of the module/component to write - * @result EC_Normal if reading was successful, error otherwise - */ - static OFCondition read(DcmItem& source, - IODRules& rules, - DcmItem& destination, - const OFString& componentName); - - /** Static helper function that writes attributes from given - * item into destination item, as determined by the provided - * rules and component name. The rules are only applied when writing - * to the destination (which may result in warning messages on the logger, - * and the whole call returning with an error). During reading from the - * source item the elements read are not validated against the rules. - * @param source The item to read from - * @param rules The rules that provide the attributes and requirements - * for these attributes - * @param destination The destination to write to - * @param componentName The name of the module/component to write - * @result EC_Normal if reading was successful, error otherwise - */ - static OFCondition write(DcmItem& source, - IODRules& rules, - DcmItem& destination, - const OFString& componentName); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * an empty rule set. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODComponent(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor, creates rules and item from scratch. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODComponent(IODComponent* parent = NULL); + + /** Assignment operator, copies contained item and rule set from rhs to + * "this" attribute set. Performs deep copy, i.e.\ the contained item + * and the rule set are copied. The parent component is set to NULL. + * @param rhs The IODComponent to be assigned + * @return Reference to this module + */ + IODComponent& operator=(const IODComponent& rhs); + + /** Copy constructor, copies reference to contained item and + * rule set to "this" attribute set. + * @param rhs The component to be assigned + */ + IODComponent(const IODComponent& rhs); + + /** Virtual Destructor + */ + virtual ~IODComponent(); + + /** Clear all attributes from the data that are handled by this module. + * An attribute is considered belonging to the module if there are rules + * marked as belonging to this module via the rule's module name. + */ + void clearData(); + + /** Set missing values by inventing "default values". Automatically + * called during write() in IODComponent; does nothing in this base + * class implementation but can be overwritten by derived classes if + * default values are desired. + */ + virtual void inventMissing(); + + /** Resets rules to their original values + */ + virtual void resetRules() = 0; + + /** Get rules handled by this module + * @return The rules + */ + OFshared_ptr getRules() + { + return m_Rules; + } + + /** Make component optional by turning all attributes requirement types of it + * to type 3. In order to reset to the attribute's original types, + * resetRules() can be used. + */ + virtual void makeOptional(); + + /** Get name of component + * @return Name of the module + */ + virtual OFString getName() const = 0; + + /** Get the data handled by this module + * @return The item containing the data of this module + */ + DcmItem& getData() + { + return *m_Item; + } + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. Only + * the returned error code will indicate error or OK. Per default, + * logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Comparison operator for IOD Components + * @param rhs The right hand side of the comparison + * @return 0, if the given object is equal to this object, other value otherwise + */ + virtual int compare(const IODComponent& rhs) const; + + /** Static helper function that reads attributes from given + * item into destination item, as determined by the provided + * rules and component name. The rules are only applied when reading + * from the source (which may result in warning messages on the logger), + * but if they could be found they are taken over into the destination + * item no matter whether the element validates against the rule. + * @param source The item to read from + * @param rules The rules that provide the attributes and requirements + * for these attributes + * @param destination The destination to write to + * @param componentName The name of the module/component to write + * @result EC_Normal if reading was successful, error otherwise + */ + static OFCondition read(DcmItem& source, IODRules& rules, DcmItem& destination, const OFString& componentName); + + /** Static helper function that writes attributes from given + * item into destination item, as determined by the provided + * rules and component name. The rules are only applied when writing + * to the destination (which may result in warning messages on the logger, + * and the whole call returning with an error). During reading from the + * source item the elements read are not validated against the rules. + * @param source The item to read from + * @param rules The rules that provide the attributes and requirements + * for these attributes + * @param destination The destination to write to + * @param componentName The name of the module/component to write + * @result EC_Normal if reading was successful, error otherwise + */ + static OFCondition write(DcmItem& source, IODRules& rules, DcmItem& destination, const OFString& componentName); protected: + /// Shared pointer to the data handled by this class. The item may contain + /// more attributes than this class is actually responsible for + OFshared_ptr m_Item; - /// Shared pointer to the data handled by this class. The item may contain - /// more attributes than this class is actually responsible for - OFshared_ptr m_Item; - - /// Rules describing the attributes governed by this class - OFshared_ptr m_Rules; - - /// The parent component (may be NULL) of this class - IODComponent* m_Parent; + /// Rules describing the attributes governed by this class + OFshared_ptr m_Rules; + /// The parent component (may be NULL) of this class + IODComponent* m_Parent; }; - /** The class IODModule is an IODComponent without parent component since * a module does always belong to the top level dataset. * Also, different from IODComponents, modules usually share data and @@ -218,38 +205,35 @@ protected: class DCMTK_DCMIOD_EXPORT IODModule : public IODComponent { public: - - /** Constructor. Similar to the one of IODComponent but no parent - * can be defined since a module is always at top level. - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * an empty rule set. - */ - IODModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor. Creates new empty data container and new empty - * ruleset. No parent component is defined (since a module is always - * on top level. - */ - IODModule(); - - /** Copy constructor, creates shallow copy - * @param rhs The module to copy from - */ - IODModule(const IODModule& rhs); - - /** Assignment operator, creates shallow copy - * @param rhs The module to copy from - * @return Returns reference to this object - */ - IODModule& operator=(const IODModule& rhs); - - /** Desctructor - */ - ~IODModule() {}; + /** Constructor. Similar to the one of IODComponent but no parent + * can be defined since a module is always at top level. + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * an empty rule set. + */ + IODModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor. Creates new empty data container and new empty + * ruleset. No parent component is defined (since a module is always + * on top level. + */ + IODModule(); + + /** Copy constructor, creates shallow copy + * @param rhs The module to copy from + */ + IODModule(const IODModule& rhs); + + /** Assignment operator, creates shallow copy + * @param rhs The module to copy from + * @return Returns reference to this object + */ + IODModule& operator=(const IODModule& rhs); + + /** Desctructor + */ + ~IODModule() {}; }; -#endif //MODBASE_H - +#endif // MODBASE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h b/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h index 23dccbab..2b3c81f0 100644 --- a/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h +++ b/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,14 +23,13 @@ #define MODCOMMONINSTANCEREF_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofvector.h" #include "dcmtk/dcmdata/dctk.h" -#include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/dcmiod/iodmacro.h" #include "dcmtk/dcmiod/iodreferences.h" - +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the Common Instance Reference Module: * @@ -50,103 +49,97 @@ class DCMTK_DCMIOD_EXPORT IODCommonInstanceReferenceModule : public IODModule { public: - - // Forward declaration (class defined later in this file) - class StudiesOtherInstancesItem; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODCommonInstanceReferenceModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODCommonInstanceReferenceModule(); - - /** Clears all data belonging to this module (rules are kept) - */ - virtual void clearData(); - - /** Destructor - */ - virtual ~IODCommonInstanceReferenceModule(); - - /** Add references - * @param references The references to be added - * @param studyInstanceUID The Study Instance UID of "this" object instance. - * It's used to decide whether the provided instances (with their - * own Study Instance UIDs) will go into the Referenced Series Sequence - * or into the Studies Containing Other Referenced Instances Sequence. - * If it is left empty, then the method tries to find "this" instances - * Study Instance UID in the internal item container which may be shared - * with other modules and thus may already provide the Study Instance - * UID (e.g. via General Study Module). - * @param clearOldData Delete any old references if OFTrue, otherwise keep them - * @result EC_Normal if successful, error otherwise - */ - virtual size_t addReferences(const IODReferences& references, - const OFString& studyInstanceUID = "", - const OFBool clearOldData = OFTrue); - - /** Read data of this module from given source item - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading, otherwise - * it is overwriten/amended. - * @result EC_Normal if successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write data of this module into given destination item - * @param destination The item to write to - * @result EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("CommonInstanceReferenceModule") - * @return Name of the module ("CommonInstanceReferenceModule") - */ - virtual OFString getName() const; - - /** Return reference to list of Referenced Series items - * @return Reference to list of Reference Series Items - */ - OFVector& getReferencedSeriesItems(); - - /** Return reference to content of Studies Containing Other Referenced Instances Sequence - * @return Reference to content of Studies Containing Other Referenced Instances Sequence - */ - OFVector& getStudiesContainingOtherReferences(); + // Forward declaration (class defined later in this file) + class StudiesOtherInstancesItem; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODCommonInstanceReferenceModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODCommonInstanceReferenceModule(); + + /** Clears all data belonging to this module (rules are kept) + */ + virtual void clearData(); + + /** Destructor + */ + virtual ~IODCommonInstanceReferenceModule(); + + /** Add references + * @param references The references to be added + * @param studyInstanceUID The Study Instance UID of "this" object instance. + * It's used to decide whether the provided instances (with their + * own Study Instance UIDs) will go into the Referenced Series Sequence + * or into the Studies Containing Other Referenced Instances Sequence. + * If it is left empty, then the method tries to find "this" instances + * Study Instance UID in the internal item container which may be shared + * with other modules and thus may already provide the Study Instance + * UID (e.g. via General Study Module). + * @param clearOldData Delete any old references if OFTrue, otherwise keep them + * @result EC_Normal if successful, error otherwise + */ + virtual size_t addReferences(const IODReferences& references, + const OFString& studyInstanceUID = "", + const OFBool clearOldData = OFTrue); + + /** Read data of this module from given source item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, otherwise + * it is overwriten/amended. + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write data of this module into given destination item + * @param destination The item to write to + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("CommonInstanceReferenceModule") + * @return Name of the module ("CommonInstanceReferenceModule") + */ + virtual OFString getName() const; + + /** Return reference to list of Referenced Series items + * @return Reference to list of Reference Series Items + */ + OFVector& getReferencedSeriesItems(); + + /** Return reference to content of Studies Containing Other Referenced Instances Sequence + * @return Reference to content of Studies Containing Other Referenced Instances Sequence + */ + OFVector& getStudiesContainingOtherReferences(); protected: - - virtual OFCondition addSeriesReference( - OFVector& container, - const IODReference& ref); + virtual OFCondition + addSeriesReference(OFVector& container, + const IODReference& ref); private: + void freeMemory(); - void freeMemory(); - - /// Vector with all items of the Referenced Series Sequence - OFVector m_ReferenceSeriesItems; + /// Vector with all items of the Referenced Series Sequence + OFVector m_ReferenceSeriesItems; - /// Name of this component ("CommonInstanceReferenceModule") - static const OFString m_ComponentName; + /// Name of this component ("CommonInstanceReferenceModule") + static const OFString m_ComponentName; - /// Items of Studies Containing Other Referenced Instances Sequence - OFVector m_StudiesContainingOtherReferencedInstancesSequence; + /// Items of Studies Containing Other Referenced Instances Sequence + OFVector m_StudiesContainingOtherReferencedInstancesSequence; }; - /** Class representing items from the Studies Containing Other Referenced Instances Sequence, * as used within the Common Instance Reference Module * @@ -159,86 +152,77 @@ class DCMTK_DCMIOD_EXPORT IODCommonInstanceReferenceModule::StudiesOtherInstance { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - StudiesOtherInstancesItem(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent = NULL); - - /** Constructor - * @param parent The parent component of this module, might be NULL - */ - StudiesOtherInstancesItem(IODComponent* parent = NULL); - - /** Destructor - */ - virtual ~StudiesOtherInstancesItem(); - - /** Clear (removes) all attributes handled by the modules of this component. - * Rules are not reset. - */ - virtual void clearData(); - - /** Read data from source item into this module - * @param source The item to read from - * @param clearOldData If OFTrue, old data is cleared first, otherwise it is - * overwritten/amended - * @result EC_Normal if successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this module's data into given destination item - * @param destination Item to write to - * @result EC_Normal if successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("StudiesContainingOtherReferencedInstancesSequence") - * @return Name of the module ("StudiesContainingOtherReferencedInstancesSequence") - */ - virtual OFString getName() const; - - /** Get Study Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Set Study Instance UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyInstanceUID(const OFString& value, - const OFBool checkValue = OFTrue); - - - /** Get Series And Instance Reference Macro - * @return Reference to the Series And Instance Reference Macro structure - */ - virtual IODSeriesAndInstanceReferenceMacro& getReferencedSeriesAndInstanceReferences(); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + StudiesOtherInstancesItem(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this module, might be NULL + */ + StudiesOtherInstancesItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~StudiesOtherInstancesItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read data from source item into this module + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared first, otherwise it is + * overwritten/amended + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write this module's data into given destination item + * @param destination Item to write to + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("StudiesContainingOtherReferencedInstancesSequence") + * @return Name of the module ("StudiesContainingOtherReferencedInstancesSequence") + */ + virtual OFString getName() const; + + /** Get Study Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Set Study Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Get Series And Instance Reference Macro + * @return Reference to the Series And Instance Reference Macro structure + */ + virtual IODSeriesAndInstanceReferenceMacro& getReferencedSeriesAndInstanceReferences(); private: + /// The name of this component ("StudiesContainingOtherReferencedInstancesSequence") + static const OFString m_ComponentName; - /// The name of this component ("StudiesContainingOtherReferencedInstancesSequence") - static const OFString m_ComponentName; - - /// The Series and Instance Reference Macro used in this item - IODSeriesAndInstanceReferenceMacro m_ReferencedSeriesAndInstance; + /// The Series and Instance Reference Macro used in this item + IODSeriesAndInstanceReferenceMacro m_ReferencedSeriesAndInstance; }; - #endif // MODCOMMONINSTANCEREF_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhequipment.h b/dcmiod/include/dcmtk/dcmiod/modenhequipment.h index 7721d3c1..a6e5367b 100644 --- a/dcmiod/include/dcmtk/dcmiod/modenhequipment.h +++ b/dcmiod/include/dcmtk/dcmiod/modenhequipment.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -38,60 +38,64 @@ class DCMTK_DCMIOD_EXPORT IODEnhGeneralEquipmentModule : public IODModule { public: - /** Convenient struct containing all information required for setting * enhanced equipment information (for use by external code) */ struct DCMTK_DCMIOD_EXPORT EquipmentInfo { - /** Default Constructor - */ - EquipmentInfo() : - m_Manufacturer(), - m_ManufacturerModelName(), - m_DeviceSerialNumber(), - m_SoftwareVersions() {} - - /** Convenience Constructor setting all values - * @param manufacturer Manufacturer - * @param manufacturerModelName Manufacturer's model name - * @param deviceSerialNumber Serial number - * @param softwareVersions Software versions - */ - EquipmentInfo(const OFString& manufacturer, - const OFString& manufacturerModelName, - const OFString& deviceSerialNumber, - const OFString& softwareVersions) : - m_Manufacturer(manufacturer), - m_ManufacturerModelName(manufacturerModelName), - m_DeviceSerialNumber(deviceSerialNumber), - m_SoftwareVersions(softwareVersions) {} - - /** Perform simple check whether all equipment data is filled in. Does not - * check VR or VM (will be checked in write() routine, though) - * @return OFTrue if data is complete, OFFalse otherwise - */ - OFBool isDataComplete() const - { - if (m_Manufacturer.empty() || m_ManufacturerModelName.empty() || m_DeviceSerialNumber.empty() || m_SoftwareVersions.empty()) + /** Default Constructor + */ + EquipmentInfo() + : m_Manufacturer() + , m_ManufacturerModelName() + , m_DeviceSerialNumber() + , m_SoftwareVersions() { - return OFFalse; } - return OFTrue; - } - /// Manufacturer (VM 1) - OFString m_Manufacturer; + /** Convenience Constructor setting all values + * @param manufacturer Manufacturer + * @param manufacturerModelName Manufacturer's model name + * @param deviceSerialNumber Serial number + * @param softwareVersions Software versions + */ + EquipmentInfo(const OFString& manufacturer, + const OFString& manufacturerModelName, + const OFString& deviceSerialNumber, + const OFString& softwareVersions) + : m_Manufacturer(manufacturer) + , m_ManufacturerModelName(manufacturerModelName) + , m_DeviceSerialNumber(deviceSerialNumber) + , m_SoftwareVersions(softwareVersions) + { + } - /// Manufacturer's Model Name (VM 1) - OFString m_ManufacturerModelName; + /** Perform simple check whether all equipment data is filled in. Does not + * check VR or VM (will be checked in write() routine, though) + * @return OFTrue if data is complete, OFFalse otherwise + */ + OFBool isDataComplete() const + { + if (m_Manufacturer.empty() || m_ManufacturerModelName.empty() || m_DeviceSerialNumber.empty() + || m_SoftwareVersions.empty()) + { + return OFFalse; + } + return OFTrue; + } - /// Device Serial Number (VM 1) - OFString m_DeviceSerialNumber; + /// Manufacturer (VM 1) + OFString m_Manufacturer; - /// Software Version(s) (VM 1-n) - OFString m_SoftwareVersions; + /// Manufacturer's Model Name (VM 1) + OFString m_ManufacturerModelName; + + /// Device Serial Number (VM 1) + OFString m_DeviceSerialNumber; + + /// Software Version(s) (VM 1-n) + OFString m_SoftwareVersions; }; /** Constructor @@ -100,8 +104,7 @@ public: * @param rules The rule set for this class. If NULL, the class creates * one from scratch and adds its values. */ - IODEnhGeneralEquipmentModule(OFshared_ptr item, - OFshared_ptr rules); + IODEnhGeneralEquipmentModule(OFshared_ptr item, OFshared_ptr rules); /** Constructor */ @@ -111,8 +114,7 @@ public: */ virtual ~IODEnhGeneralEquipmentModule(); - static OFCondition create(const EquipmentInfo& info, - IODEnhGeneralEquipmentModule* equipment); + static OFCondition create(const EquipmentInfo& info, IODEnhGeneralEquipmentModule* equipment); /** Resets rules to their original values. */ @@ -128,64 +130,56 @@ public: * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getManufacturer(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getManufacturer(OFString& value, const signed long pos = 0) const; /** Get Manufacturer's Model Name * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getManufacturerModelName(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getManufacturerModelName(OFString& value, const signed long pos = 0) const; /** Get Device Serial Number * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getDeviceSerialNumber(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getDeviceSerialNumber(OFString& value, const signed long pos = 0) const; /** Get Software Version(s) * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getSoftwareVersions(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getSoftwareVersions(OFString& value, const signed long pos = 0) const; /** Set Manufacturer * @param value Value to be set (single value only) or "" for no value * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setManufacturer(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setManufacturer(const OFString& value, const OFBool checkValue = OFTrue); /** Set Manufacturer's Model Name * @param value Value to be set (single value only) or "" for no value * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setManufacturerModelName(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setManufacturerModelName(const OFString& value, const OFBool checkValue = OFTrue); /** Set Device Serial Number * @param value Value to be set (single value only) or "" for no value * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setDeviceSerialNumber(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setDeviceSerialNumber(const OFString& value, const OFBool checkValue = OFTrue); /** Set Software Version(s) * @param value Value to be set (possibly multi-valued) or "" for no value * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSoftwareVersions(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setSoftwareVersions(const OFString& value, const OFBool checkValue = OFTrue); /** Set all equipment information at once * @param info The equipment information to be set. @@ -194,10 +188,8 @@ public: virtual OFCondition set(const EquipmentInfo& info); private: - /// Name of the module ("EnhancedEquipmentModule") OFString m_ModuleName; }; - #endif // MODENHEQUIPMENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhusimage.h b/dcmiod/include/dcmtk/dcmiod/modenhusimage.h index 37401913..b7293b02 100644 --- a/dcmiod/include/dcmtk/dcmiod/modenhusimage.h +++ b/dcmiod/include/dcmtk/dcmiod/modenhusimage.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2020, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,8 @@ #define MODENHUSIMAGE_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modbase.h" /** Class representing the Enhanced US Image Module: * @@ -67,527 +67,471 @@ class DCMTK_DCMIOD_EXPORT IODEnhUSImageModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set where this classes rules are added to. If NULL, the - * class creates an empty rule set. - */ - IODEnhUSImageModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODEnhUSImageModule(); - - /** Destructor - */ - virtual ~IODEnhUSImageModule(); - - /** Resets rules to their original values. - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("EnhancedUSImageModule") - */ - virtual OFString getName() const; - - /** Read attributes from given item into this class. Overwrites - * fucntion of base class IODComponent. - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item. Overwrites - * function of base class IODComponent. - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Get Image Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageType(OFString &value, - const signed long pos = 0); - - /** Get Samples Per Pixel - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSamplesPerPixel(Uint16& value, - const unsigned long pos = 0); - - /** Get Photometric Interpretation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPhotometricInterpretation(OFString& value, - const signed long pos = 0); - - /** Get Rows - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRows(Uint16& value, - const unsigned long pos = 0); - - /** Get Columns - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getColumns(Uint16& value, - const unsigned long pos = 0); - /** Get Bits Allocated - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBitsAllocated(Uint16& value, - const unsigned long pos = 0); - - /** Get Bits Stored - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBitsStored(Uint16& value, - const unsigned long pos = 0); - - /** Get High Bit - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getHighBit(Uint16& value, - const unsigned long pos = 0); - - /** Get Pixel Representation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPixelRepresentation(Uint16& value, - const unsigned long pos = 0); - - /** Get Dimension Organization Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDimensionOrganizationType(OFString& value, - const signed long pos = 0); - - /** Get Acquisition DateTime - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionDateTime(OFString& value, - const signed long pos = 0); - - /** Get Acquisition Duration - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionDuration(Float64& value, - const unsigned long pos = 0); - - /** Get Pixel Spacing - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPixelSpacing(Float64& value, - const unsigned long pos = 0); - - /** Get Position Measuring Device - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPositionMeasuringDevice(OFString& value, - const signed long pos = 0); - - /** Get Lossy Image Compression - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompression(OFString& value, - const signed long pos = 0); - - /** Get Lossy Image Compression Ratio - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompressionRatio(Float64& value, - const unsigned long pos = 0); - - /** Get Lossy Image Compression Method - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompressionMethod(OFString& value, - const signed long pos = 0); - - /** Get Presentation LUT Shape - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPresentationLUTShape(OFString& value, - const signed long pos = 0); - /** Get Rescale Slope - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRescaleSlope(Float64& value, - const unsigned long pos = 0); - /** Get Rescale Intercept - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRescaleIntercept(OFString& value, - const signed long pos = 0); - - /** Get Burned-In Annotation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBurnedInAnnotation(OFString& value, - const signed long pos = 0); - /** Get Recognizable Visual Features - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRecognizableVisibleFeatures(OFString& value, - const signed long pos = 0); - /** Get Mandatory View And Slice Progression Direction - * @return Reference to Mandatory View And Slice Progression Direction - */ - virtual MandatoryViewAndSliceProgressionDirectionMacro& getMandatoryViewAndSliceProgressionDirection(); - - /** Get Anatomy - * @return Reference to Anatomy - */ - virtual GeneralAnatomyMacro& getAnatomy(); - - /** Get Transducer Scan Pattern - * @return Reference to Transducer Scan Pattern - */ - virtual CodeSequenceMacro& getTransducerScanPattern(); - - /** Get Transducer Geometry Code - * @return Reference to Transducer Geometry - */ - virtual CodeSequenceMacro& getTransducerGeometry(); - - /** Get Transducer Beam Steering - * @return Reference to Transducer Beam Steering - */ - virtual OFVector& getTransducerBeamSteering(); - - /** Get Transducer Application - * @return Reference to Transducer Application - */ - virtual CodeSequenceMacro& getTransducerApplication(); - - /** Get Processing Function - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getProcessingFunction(OFString& value, - const signed long pos = 0); - /** Get Mechanical Index - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getMechanicalIndex(Float64& value, - const unsigned long pos = 0); - - /** Get Bone Thermal Index - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBoneThermalIndex(Float64& value, - const unsigned long pos = 0); - - /** Get Cranial Thermal Index - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getCranialThermalIndex(Float64& value, - const unsigned long pos = 0); - - /** Get Soft Tissue Thermal Index - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all values - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSoftTissueThermalIndex(Float64& value, - const unsigned long pos = 0); - - /** Get Depth(s) of Focus - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDepthsOfFocus(Float64& value, - const unsigned long pos = 0); - - /** Get Depth(s) of Scan Field - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDepthsOfScanField(Float64& value, - const unsigned long pos = 0); - - /** Set Image Type. Image Type contains up to four values. Value 3 and 4 are - * optional and can be left empty if desired. The values in their order - * of occurrence are: - * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED - * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be - * influenced through this function. - * 3) Image Flavor: Defined Terms listed in the standard - * 4) Derived Pixel Contrast: Defined Terms listed in the standard - * @param pixelDataChar Value 1 of Image Type - * @param imageFlavor Value 3 of Image Type - * @param derivedPixelContrast Value 4 of Image Type - * @param checkValue If OFTrue, the value is checked for conformance. - * @return EC_Normal if setting was successful, error otherwise. - */ - virtual OFCondition setImageType(const DcmIODTypes::IOD_ENHUSIMAGETYPE pixelDataChar, - const OFString& imageFlavor = "", - const OFString& derivedPixelContrast = "", - const OFBool checkValue = OFTrue); - - /** Set Rows - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRows(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Columns - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setColumns(const Uint16 value, - const OFBool checkValue = OFTrue); - /** Set Bits Allocated - * @param value Value to be set, permitted values: 8 or 16 - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBitsAllocated(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Bits Stored - * @param value Value to be set, permitted values: 8 or 16 - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBitsStored(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set High Bit - * @param value Value to be set, permitted values: 7 or 15 - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setHighBit(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Dimension Organization Type - * @param value Value to be set, permitted values: "3D" or "3D_TEMPORAL" - * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDimensionOrganizationType(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition DateTime - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DT) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionDateTime(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition Duration - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionDuration(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Pixel Spacing - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (2) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPixelSpacing(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Position Measuring Device - * @param value Value to be set, permitted values: "RIGID" or "FREEHAND" - * @param checkValue Check 'value' for conformance if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPositionMeasuringDevice(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression - * @param value Value to be set, permitted values: "00" (not lossy compressed) or "01" (lossy compressed) - * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompression(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression Ratio - * @param value Value to be set, including VR (DS) and VM (1-n) - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompressionRatio(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression Method - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (CS) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompressionMethod(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Recognizable Visual Features - * @param value Value to be set, permitted values: "YES" or "NO" - * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRecognizableVisibleFeatures(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Processing Funcion - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (LO) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setProcessingFunction(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Mechanical Index - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setMechanicalIndex(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Bone Thermal Index - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBoneThermalIndex(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Cranial Thermal Index - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setCranialThermalIndex(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Soft Tissue Thermal Index - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSoftTissueThermalIndex(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Depth(s) of Focus - * @param value Value to be set - * @param pos Index of the value to set (0..vm-1) - * @param checkValue Check 'value'. Not evaluated (here for consistency with - * other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDepthsOfFocus(const Float64 value, - const unsigned long pos, - const OFBool checkValue = OFTrue); - - /** Set Depth(s) of Focus (convenience function) - * @param values Value(s) to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency with - * other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDepthsOfFocus(const OFVector& values, - const OFBool checkValue = OFTrue); - - /** Set Depth(s) of Scan Field - * @param value Value to be set - * @param checkValue Check 'value' for conformance if enabled, including VR (IS) and VM (1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDepthsOfScanField(const OFString& value, - const OFBool checkValue = OFTrue); - + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + IODEnhUSImageModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODEnhUSImageModule(); + + /** Destructor + */ + virtual ~IODEnhUSImageModule(); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("EnhancedUSImageModule") + */ + virtual OFString getName() const; + + /** Read attributes from given item into this class. Overwrites + * fucntion of base class IODComponent. + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item. Overwrites + * function of base class IODComponent. + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get Image Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageType(OFString& value, const signed long pos = 0); + + /** Get Samples Per Pixel + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSamplesPerPixel(Uint16& value, const unsigned long pos = 0); + + /** Get Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPhotometricInterpretation(OFString& value, const signed long pos = 0); + + /** Get Rows + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRows(Uint16& value, const unsigned long pos = 0); + + /** Get Columns + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getColumns(Uint16& value, const unsigned long pos = 0); + /** Get Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsAllocated(Uint16& value, const unsigned long pos = 0); + + /** Get Bits Stored + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsStored(Uint16& value, const unsigned long pos = 0); + + /** Get High Bit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getHighBit(Uint16& value, const unsigned long pos = 0); + + /** Get Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelRepresentation(Uint16& value, const unsigned long pos = 0); + + /** Get Dimension Organization Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationType(OFString& value, const signed long pos = 0); + + /** Get Acquisition DateTime + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDateTime(OFString& value, const signed long pos = 0); + + /** Get Acquisition Duration + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDuration(Float64& value, const unsigned long pos = 0); + + /** Get Pixel Spacing + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelSpacing(Float64& value, const unsigned long pos = 0); + + /** Get Position Measuring Device + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPositionMeasuringDevice(OFString& value, const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompression(OFString& value, const signed long pos = 0); + + /** Get Lossy Image Compression Ratio + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(Float64& value, const unsigned long pos = 0); + + /** Get Lossy Image Compression Method + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionMethod(OFString& value, const signed long pos = 0); + + /** Get Presentation LUT Shape + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPresentationLUTShape(OFString& value, const signed long pos = 0); + /** Get Rescale Slope + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleSlope(Float64& value, const unsigned long pos = 0); + /** Get Rescale Intercept + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleIntercept(OFString& value, const signed long pos = 0); + + /** Get Burned-In Annotation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBurnedInAnnotation(OFString& value, const signed long pos = 0); + /** Get Recognizable Visual Features + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRecognizableVisibleFeatures(OFString& value, const signed long pos = 0); + /** Get Mandatory View And Slice Progression Direction + * @return Reference to Mandatory View And Slice Progression Direction + */ + virtual MandatoryViewAndSliceProgressionDirectionMacro& getMandatoryViewAndSliceProgressionDirection(); + + /** Get Anatomy + * @return Reference to Anatomy + */ + virtual GeneralAnatomyMacro& getAnatomy(); + + /** Get Transducer Scan Pattern + * @return Reference to Transducer Scan Pattern + */ + virtual CodeSequenceMacro& getTransducerScanPattern(); + + /** Get Transducer Geometry Code + * @return Reference to Transducer Geometry + */ + virtual CodeSequenceMacro& getTransducerGeometry(); + + /** Get Transducer Beam Steering + * @return Reference to Transducer Beam Steering + */ + virtual OFVector& getTransducerBeamSteering(); + + /** Get Transducer Application + * @return Reference to Transducer Application + */ + virtual CodeSequenceMacro& getTransducerApplication(); + + /** Get Processing Function + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getProcessingFunction(OFString& value, const signed long pos = 0); + /** Get Mechanical Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getMechanicalIndex(Float64& value, const unsigned long pos = 0); + + /** Get Bone Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBoneThermalIndex(Float64& value, const unsigned long pos = 0); + + /** Get Cranial Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCranialThermalIndex(Float64& value, const unsigned long pos = 0); + + /** Get Soft Tissue Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSoftTissueThermalIndex(Float64& value, const unsigned long pos = 0); + + /** Get Depth(s) of Focus + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDepthsOfFocus(Float64& value, const unsigned long pos = 0); + + /** Get Depth(s) of Scan Field + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDepthsOfScanField(Sint32& value, const unsigned long pos = 0); + + /** Set Image Type. Image Type contains up to four values. Value 3 and 4 are + * optional and can be left empty if desired. The values in their order + * of occurrence are: + * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED + * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be + * influenced through this function. + * 3) Image Flavor: Defined Terms listed in the standard + * 4) Derived Pixel Contrast: Defined Terms listed in the standard + * @param pixelDataChar Value 1 of Image Type + * @param imageFlavor Value 3 of Image Type + * @param derivedPixelContrast Value 4 of Image Type + * @param checkValue If OFTrue, the value is checked for conformance. + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setImageType(const DcmIODTypes::IOD_ENHUSIMAGETYPE pixelDataChar, + const OFString& imageFlavor = "", + const OFString& derivedPixelContrast = "", + const OFBool checkValue = OFTrue); + + /** Set Rows + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRows(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Columns + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setColumns(const Uint16 value, const OFBool checkValue = OFTrue); + /** Set Bits Allocated + * @param value Value to be set, permitted values: 8 or 16 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsAllocated(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Bits Stored + * @param value Value to be set, permitted values: 8 or 16 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsStored(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set High Bit + * @param value Value to be set, permitted values: 7 or 15 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setHighBit(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Dimension Organization Type + * @param value Value to be set, permitted values: "3D" or "3D_TEMPORAL" + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition DateTime + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DT) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDateTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition Duration + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDuration(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Pixel Spacing + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (2) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelSpacing(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Position Measuring Device + * @param value Value to be set, permitted values: "RIGID" or "FREEHAND" + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPositionMeasuringDevice(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression + * @param value Value to be set, permitted values: "00" (not lossy compressed) or "01" (lossy compressed) + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompression(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Ratio + * @param value Value to be set, including VR (DS) and VM (1-n) + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionRatio(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Method + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionMethod(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Recognizable Visual Features + * @param value Value to be set, permitted values: "YES" or "NO" + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRecognizableVisibleFeatures(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Processing Funcion + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (LO) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setProcessingFunction(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Mechanical Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setMechanicalIndex(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Bone Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBoneThermalIndex(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Cranial Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setCranialThermalIndex(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Soft Tissue Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSoftTissueThermalIndex(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Focus + * @param value Value to be set + * @param pos Index of the value to set (0..vm-1) + * @param checkValue Check 'value'. Not evaluated (here for consistency with + * other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setDepthsOfFocus(const Float64 value, const unsigned long pos, const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Focus (convenience function) + * @param values Value(s) to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency with + * other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDepthsOfFocus(const OFVector& values, const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Scan Field + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (IS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDepthsOfScanField(const OFString& value, const OFBool checkValue = OFTrue); private: + /// This module's name ("EnhancedUSImageModule") + static const OFString m_ModuleName; - /// This module's name ("EnhancedUSImageModule") - static const OFString m_ModuleName; - - /// Mandatory View and Slice Progression Direction - MandatoryViewAndSliceProgressionDirectionMacro m_MandatoryViewAndSliceProgressionDirection; + /// Mandatory View and Slice Progression Direction + MandatoryViewAndSliceProgressionDirectionMacro m_MandatoryViewAndSliceProgressionDirection; - /// General Anatomy Mandatory Macro - GeneralAnatomyMacro m_Anatomy; + /// General Anatomy Mandatory Macro + GeneralAnatomyMacro m_Anatomy; - /// Item of Transducer Scan Pattern Code Sequence - CodeSequenceMacro m_TransducerScanPattern; + /// Item of Transducer Scan Pattern Code Sequence + CodeSequenceMacro m_TransducerScanPattern; - /// Item of Transducer Geometry Code Sequence - CodeSequenceMacro m_TransducerGeometry; + /// Item of Transducer Geometry Code Sequence + CodeSequenceMacro m_TransducerGeometry; - /// Item of Transducer Beam Steering Code Sequence - OFVector m_TransducerBeamSteering; + /// Item of Transducer Beam Steering Code Sequence + OFVector m_TransducerBeamSteering; - /// Item of Transducer Application Code Sequence - CodeSequenceMacro m_TransducerApplication; + /// Item of Transducer Application Code Sequence + CodeSequenceMacro m_TransducerApplication; }; #endif // MODENHUSIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhusseries.h b/dcmiod/include/dcmtk/dcmiod/modenhusseries.h index cfeaccb7..22e81290 100644 --- a/dcmiod/include/dcmtk/dcmiod/modenhusseries.h +++ b/dcmiod/include/dcmtk/dcmiod/modenhusseries.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,112 +23,106 @@ #define MODENHUSSERIES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofvector.h" -#include "dcmtk/ofstd/ofoption.h" -#include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the Enhanced Ultrasound Series Module: * - * Notation: "Attribute name: (VR, VM, Requirement Type)" - * Modality: (CS, 1, 1) - * Referenced Performed Procedure Step Sequence: (SQ, 1, 1C) - * > SOP Instance Reference Macro - * Performed Protocol Code Sequence: (SQ, 1, 1C) - * > Code Sequence Macro - * Not yet explicitly supported: - * ---------------------------------------------- - * > Protocol Context Sequence: (SQ, 1-n, 3) - * >> Content Item Macro - * >> Content Item Modifier Sequence: (SQ, 1-n, 3) - * >>> Content Item Macro - * ---------------------------------------------- + * Notation: "Attribute name: (VR, VM, Requirement Type)"\n + * Modality: (CS, 1, 1)\n + * Referenced Performed Procedure Step Sequence: (SQ, 1, 1C)\n + * > SOP Instance Reference Macro\n + * Performed Protocol Code Sequence: (SQ, 1, 1C)\n + * > Code Sequence Macro\n\n + * + * Not yet explicitly supported:\n + * ----------------------------------------------\n + * > Protocol Context Sequence: (SQ, 1-n, 3)\n + * >> Content Item Macro\n + * >> Content Item Modifier Sequence: (SQ, 1-n, 3)\n + * >>> Content Item Macro\n + * ----------------------------------------------\n * Performed Protocol Type: (CS, 1, 1C) */ class DCMTK_DCMIOD_EXPORT IODEnhancedUSSeriesModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODEnhancedUSSeriesModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODEnhancedUSSeriesModule(); - - /** Destructor - */ - virtual ~IODEnhancedUSSeriesModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("EnhancedUSSeriesModule") - * @return Name of the module ("EnhancedUSSeriesModule") - */ - virtual OFString getName() const; - - /** Read data into this module from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this module to given item - * @param destination The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Get Modality, always returns "US" - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getModality(OFString &value, - const signed long pos = 0) const; - - - /** Get Referenced Performed Procedure Step - * @return Reference to the Referenced Performed Procedure Step information - */ - virtual SOPInstanceReferenceMacro& getReferencedPPS(); - - /** Get Performed Protocol Code - * @return Reference to the Performed Protocol information - */ - virtual CodeSequenceMacro& getPerformedProtocolCode(); - - /** Get Performed Protocol Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPerformedProtocolType(OFString &value, - const signed long pos = 0) const; + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODEnhancedUSSeriesModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODEnhancedUSSeriesModule(); + + /** Destructor + */ + virtual ~IODEnhancedUSSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("EnhancedUSSeriesModule") + * @return Name of the module ("EnhancedUSSeriesModule") + */ + virtual OFString getName() const; + + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get Modality, always returns "US" + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString& value, const signed long pos = 0) const; + + /** Get Referenced Performed Procedure Step + * @return Reference to the Referenced Performed Procedure Step information + */ + virtual SOPInstanceReferenceMacro& getReferencedPPS(); + + /** Get Performed Protocol Code + * @return Reference to the Performed Protocol information + */ + virtual CodeSequenceMacro& getPerformedProtocolCode(); + + /** Get Performed Protocol Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPerformedProtocolType(OFString& value, const signed long pos = 0) const; private: + /// The name of this module ("EnhancedUSSeriesModule") + static const OFString m_ModuleName; - /// The name of this module ("EnhancedUSSeriesModule") - static const OFString m_ModuleName; - - /// Referenced Performed Procedure Step Sequence - SOPInstanceReferenceMacro m_ReferencedPerformedProcedureStep; + /// Referenced Performed Procedure Step Sequence + SOPInstanceReferenceMacro m_ReferencedPerformedProcedureStep; - /// Performed Protocol Code Sequence (so far, without optional data) - CodeSequenceMacro m_PerformedProtocolCode; + /// Performed Protocol Code Sequence (so far, without optional data) + CodeSequenceMacro m_PerformedProtocolCode; }; #endif // MODENHUSSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modequipment.h b/dcmiod/include/dcmtk/dcmiod/modequipment.h index 77e72d7e..c5edb189 100644 --- a/dcmiod/include/dcmtk/dcmiod/modequipment.h +++ b/dcmiod/include/dcmtk/dcmiod/modequipment.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -42,47 +42,50 @@ class DCMTK_DCMIOD_EXPORT IODGeneralEquipmentModule : public IODModule { public: - /** Convenient struct containing commonly used equipment information * (for use by external code) */ struct DCMTK_DCMIOD_EXPORT EquipmentInfo { - /** Default Constructor - */ - EquipmentInfo() : - m_Manufacturer(), - m_ManufacturerModelName(), - m_DeviceSerialNumber(), - m_SoftwareVersions() {} - - /** Convenience Constructor setting commonly used values - * @param manufacturer Manufacturer - * @param manufacturerModelName Manufacturer's model name - * @param deviceSerialNumber Serial number - * @param softwareVersions Software versions - */ - EquipmentInfo(const OFString& manufacturer, - const OFString& manufacturerModelName, - const OFString& deviceSerialNumber, - const OFString& softwareVersions) : - m_Manufacturer(manufacturer), - m_ManufacturerModelName(manufacturerModelName), - m_DeviceSerialNumber(deviceSerialNumber), - m_SoftwareVersions(softwareVersions) {} - - /// Manufacturer (VM 1) - OFString m_Manufacturer; - - /// Manufacturer's Model Name (VM 1) - OFString m_ManufacturerModelName; - - /// Device Serial Number (VM 1) - OFString m_DeviceSerialNumber; - - /// Software Version(s) (VM 1-n) - OFString m_SoftwareVersions; + /** Default Constructor + */ + EquipmentInfo() + : m_Manufacturer() + , m_ManufacturerModelName() + , m_DeviceSerialNumber() + , m_SoftwareVersions() + { + } + + /** Convenience Constructor setting commonly used values + * @param manufacturer Manufacturer + * @param manufacturerModelName Manufacturer's model name + * @param deviceSerialNumber Serial number + * @param softwareVersions Software versions + */ + EquipmentInfo(const OFString& manufacturer, + const OFString& manufacturerModelName, + const OFString& deviceSerialNumber, + const OFString& softwareVersions) + : m_Manufacturer(manufacturer) + , m_ManufacturerModelName(manufacturerModelName) + , m_DeviceSerialNumber(deviceSerialNumber) + , m_SoftwareVersions(softwareVersions) + { + } + + /// Manufacturer (VM 1) + OFString m_Manufacturer; + + /// Manufacturer's Model Name (VM 1) + OFString m_ManufacturerModelName; + + /// Device Serial Number (VM 1) + OFString m_DeviceSerialNumber; + + /// Software Version(s) (VM 1-n) + OFString m_SoftwareVersions; }; /** Constructor @@ -91,8 +94,7 @@ public: * @param rules The rule set for this class. If NULL, the class creates * one from scratch and adds its values. */ - IODGeneralEquipmentModule(OFshared_ptr item, - OFshared_ptr rules); + IODGeneralEquipmentModule(OFshared_ptr item, OFshared_ptr rules); /** Constructor */ @@ -103,7 +105,7 @@ public: virtual ~IODGeneralEquipmentModule(); /** Resets rules to their original values - */ + */ virtual void resetRules(); /** Get name of module @@ -116,63 +118,55 @@ public: * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getManufacturer(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getManufacturer(OFString& value, const signed long pos = 0) const; /** Get Institution Name * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getInstitutionName(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getInstitutionName(OFString& value, const signed long pos = 0) const; /** Get Institution Address * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getInstitutionAddress(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getInstitutionAddress(OFString& value, const signed long pos = 0) const; /** Get Station Name * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getStationName(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getStationName(OFString& value, const signed long pos = 0) const; /** Get Institutional Department Name * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getInstitutionalDepartmentName(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getInstitutionalDepartmentName(OFString& value, const signed long pos = 0) const; /** Get Manufacturer's Model Name * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getManufacturerModelName(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getManufacturerModelName(OFString& value, const signed long pos = 0) const; /** Get Device Serial Number * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getDeviceSerialNumber(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getDeviceSerialNumber(OFString& value, const signed long pos = 0) const; /** Get Software Version(s) * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getSoftwareVersions(OFString &value, - const signed long pos = 0) const; + virtual OFCondition getSoftwareVersions(OFString& value, const signed long pos = 0) const; /** Set Manufacturer * @param value Value to be set (single value only) or "" for no value @@ -180,8 +174,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setManufacturer(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setManufacturer(const OFString& value, const OFBool checkValue = OFTrue); /** Set Institution Name * @param value Value to be set (single value only) or "" for no value @@ -189,8 +182,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setInstitutionName(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setInstitutionName(const OFString& value, const OFBool checkValue = OFTrue); /** Set Institution Address * @param value Value to be set (single value only) or "" for no value @@ -198,8 +190,7 @@ public: * with other setter functions). * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setInstitutionAddress(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setInstitutionAddress(const OFString& value, const OFBool checkValue = OFTrue); /** Set Station Name * @param value Value to be set (single value only) or "" for no value @@ -207,8 +198,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setStationName(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setStationName(const OFString& value, const OFBool checkValue = OFTrue); /** Set Institutional Department Name * @param value Value to be set (single value only) or "" for no value @@ -216,8 +206,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setInstutionalDepartmentName(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setInstutionalDepartmentName(const OFString& value, const OFBool checkValue = OFTrue); /** Set Manufacturer's Model Name * @param value Value to be set (single value only) or "" for no value @@ -225,8 +214,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setManufacturerModelName(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setManufacturerModelName(const OFString& value, const OFBool checkValue = OFTrue); /** Set Device Serial Number * @param value Value to be set (single value only) or "" for no value @@ -234,8 +222,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setDeviceSerialNumber(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setDeviceSerialNumber(const OFString& value, const OFBool checkValue = OFTrue); /** Set Software Version(s) * @param value Value to be set (possibly multi-valued) or "" for no value @@ -243,14 +230,11 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSoftwareVersions(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setSoftwareVersions(const OFString& value, const OFBool checkValue = OFTrue); private: - /// Name of the module ("GeneralEquipmentModule") OFString m_ModuleName; }; - #endif // MODEQUIPMENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h b/dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h index 05072287..a49c3395 100644 --- a/dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h +++ b/dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,8 @@ #define MODFLOATINGPOINTIMAGEPIXEL_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/modimagepixelbase.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/modimagepixelbase.h" /** Class representing Floating Point Image Pixel Module: * @@ -41,100 +41,90 @@ class DCMTK_DCMIOD_EXPORT IODFloatingPointImagePixelModule : public IODImagePixe { public: - - /// Data type of pixels - typedef Float32 value_type; - - static const DcmTagKey pixel_data_tag; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODFloatingPointImagePixelModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODFloatingPointImagePixelModule(); - - /** Destructor - */ - virtual ~IODFloatingPointImagePixelModule(); - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("FloatingPointImagePixelModule") - */ - virtual OFString getName() const; - - /** Get pixel data type, always returns DataType::FLOAT for this class. - * @return The data type of the pixel data - */ - virtual DataType getDataType() const; - - /** Get Float Pixel Padding Value - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFloatPixelPaddingValue(Float32& value, - const signed long pos = 0); - - /** Get Float Pixel Padding Range Limit - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFloatPixelPaddingRangeLimit(Float32& value, - const signed long pos = 0); - - /** Set Float Pixel Pixel Padding Value - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (FL) and consistency - * with other attributes if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setFloatPixelPaddingValue(const Float32 value, - const OFBool checkValue = OFTrue); - - /** Set Float Pixel Padding Range Limit - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (FL) and consistency - * with other attributes if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setFloatPixelPaddingRangeLimit(const Float32 value, - const OFBool checkValue = OFTrue); + /// Data type of pixels + typedef Float32 value_type; + + static const DcmTagKey pixel_data_tag; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODFloatingPointImagePixelModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODFloatingPointImagePixelModule(); + + /** Destructor + */ + virtual ~IODFloatingPointImagePixelModule(); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("FloatingPointImagePixelModule") + */ + virtual OFString getName() const; + + /** Get pixel data type, always returns DataType::FLOAT for this class. + * @return The data type of the pixel data + */ + virtual DataType getDataType() const; + + /** Get Float Pixel Padding Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloatPixelPaddingValue(Float32& value, const unsigned long pos = 0); + + /** Get Float Pixel Padding Range Limit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloatPixelPaddingRangeLimit(Float32& value, const unsigned long pos = 0); + + /** Set Float Pixel Pixel Padding Value + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (FL) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFloatPixelPaddingValue(const Float32 value, const OFBool checkValue = OFTrue); + + /** Set Float Pixel Padding Range Limit + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (FL) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFloatPixelPaddingRangeLimit(const Float32 value, const OFBool checkValue = OFTrue); private: - - /// This module's name ("FloatingPointImagePixelModule") - static const OFString m_ModuleName; - + /// This module's name ("FloatingPointImagePixelModule") + static const OFString m_ModuleName; }; - /** Class representing Double Floating Point Image Pixel Module: * * Samples Per Pixel: (US, 1, 1) @@ -146,101 +136,92 @@ private: * Double Float Pixel Padding Value: (FD, 1, 3) * Double Float Pixel Padding Range Limit: (FD, 1, 1C) */ -class DCMTK_DCMIOD_EXPORT IODDoubleFloatingPointImagePixelModule: public IODImagePixelBase +class DCMTK_DCMIOD_EXPORT IODDoubleFloatingPointImagePixelModule : public IODImagePixelBase { public: - - /// Data type of pixels - typedef Float64 value_type; - - static const DcmTagKey pixel_data_tag; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODDoubleFloatingPointImagePixelModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODDoubleFloatingPointImagePixelModule(); - - /** Destructor - */ - virtual ~IODDoubleFloatingPointImagePixelModule(); - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("DoubleFloatingPointImagePixelModule") - */ - virtual OFString getName() const; - - /** Get pixel data type, always returns DataType::DOUBLE for this class. - * @return The data type of the pixel data - */ - virtual DataType getDataType() const; - - /** Get Double Float Pixel Padding Value - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDoubleFloatPixelPaddingValue(Float64& value, - const signed long pos = 0); - - /** Get Double Float Pixel Padding Range Limit - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDoubleFloatPixelPaddingRangeLimit(Float64& value, - const signed long pos = 0); - - /** Set Double Float Pixel Pixel Padding Value - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (FD) and consistency - * with other attributes if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDoubleFloatPixelPaddingValue(const Float64 value, - const OFBool checkValue = OFTrue); - - /** Set Double Float Pixel Padding Range Limit - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (FD) and consistency - * with other attributes if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDoubleFloatPixelPaddingRangeLimit(const Float64 value, - const OFBool checkValue = OFTrue); + /// Data type of pixels + typedef Float64 value_type; + + static const DcmTagKey pixel_data_tag; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODDoubleFloatingPointImagePixelModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODDoubleFloatingPointImagePixelModule(); + + /** Destructor + */ + virtual ~IODDoubleFloatingPointImagePixelModule(); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("DoubleFloatingPointImagePixelModule") + */ + virtual OFString getName() const; + + /** Get pixel data type, always returns DataType::DOUBLE for this class. + * @return The data type of the pixel data + */ + virtual DataType getDataType() const; + + /** Get Double Float Pixel Padding Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDoubleFloatPixelPaddingValue(Float64& value, const unsigned long pos = 0); + + /** Get Double Float Pixel Padding Range Limit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDoubleFloatPixelPaddingRangeLimit(Float64& value, const unsigned long pos = 0); + + /** Set Double Float Pixel Pixel Padding Value + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (FD) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDoubleFloatPixelPaddingValue(const Float64 value, const OFBool checkValue = OFTrue); + + /** Set Double Float Pixel Padding Range Limit + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (FD) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDoubleFloatPixelPaddingRangeLimit(const Float64 value, const OFBool checkValue = OFTrue); private: - - /// This module's name ("DoubleFloatingPointImagePixelModule") - static const OFString m_ModuleName; - + /// This module's name ("DoubleFloatingPointImagePixelModule") + static const OFString m_ModuleName; }; #endif // MODFLOATINGPOINTIMAGEPIXEL_H diff --git a/dcmiod/include/dcmtk/dcmiod/modfor.h b/dcmiod/include/dcmtk/dcmiod/modfor.h index 76d7519f..9f14a90d 100644 --- a/dcmiod/include/dcmtk/dcmiod/modfor.h +++ b/dcmiod/include/dcmtk/dcmiod/modfor.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -35,81 +35,72 @@ class DCMTK_DCMIOD_EXPORT IODFoRModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODFoRModule(OFshared_ptr item, - OFshared_ptr rules); - /** Constructor - */ - IODFoRModule(); - - /** Destructor - */ - virtual ~IODFoRModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("FrameOfReferenceModule") - */ - virtual OFString getName() const; - - /** Get Frame of Reference UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getFrameOfReferenceUID(OFString &value, - const signed long pos = 0) const; - - /** Get Position Reference Indicator - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPositionReferenceIndicator(OFString &value, - const signed long pos = 0) const; - - /** Set Frame of Reference UID - * @param value Value to be set (single value only). If an empty string is passed, - * the value "1" is set when displaying or writing the document since - * the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setFrameOfReferenceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Position Reference Indicator - * @param value Value to be set (single value only). If an empty string is passed, - * the value "1" is set when displaying or writing the document since - * the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPositionReferenceIndicator(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Make sure that the module contains a Frame of Reference Instance UID, i.e.\ - * a new one is created if empty. An invalid UID is corrected if desired. - * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing - * - */ - void ensureFrameOfReferenceUID(const OFBool correctInvalid = OFFalse); - + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODFoRModule(OFshared_ptr item, OFshared_ptr rules); + /** Constructor + */ + IODFoRModule(); + + /** Destructor + */ + virtual ~IODFoRModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("FrameOfReferenceModule") + */ + virtual OFString getName() const; + + /** Get Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFrameOfReferenceUID(OFString& value, const signed long pos = 0) const; + + /** Get Position Reference Indicator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPositionReferenceIndicator(OFString& value, const signed long pos = 0) const; + + /** Set Frame of Reference UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFrameOfReferenceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Position Reference Indicator + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPositionReferenceIndicator(const OFString& value, const OFBool checkValue = OFTrue); + + /** Make sure that the module contains a Frame of Reference Instance UID, i.e.\ + * a new one is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + * + */ + void ensureFrameOfReferenceUID(const OFBool correctInvalid = OFFalse); private: - - /// Module name "FrameOfReferenceModule" - static const OFString m_ModuleName; - + /// Module name "FrameOfReferenceModule" + static const OFString m_ModuleName; }; #endif // MODFOR_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h b/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h index 7cb3402f..8d4a09a4 100644 --- a/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -26,336 +26,311 @@ #include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" - /** Class representing the General Image Module: - * - * Instance Number: (IS, 1, 2) - * Patient Orientation: (CS, 2, 2) - * Content Date: (DA, 1, 2C) - * Content Time: (TM, 1, 2C) - * Image Type: (CS, 1, 2-n) - * Acquisition Number (IS, 1, 3) - * Acquisition Date (DA, 1, 3) - * Acquisition Time (TM, 1, 3) - * Acquisition Date Time (DT, 1, 3) - * Image Comments (LT, 1, 3) - * Burned In Annotation (CS, 1, 3) - * Recognizable Visual Features (CS, 1, 3) - * Lossy Image Compression (CS, 1, 3) - * Lossy Image Compression Ratio (DS, 1, 3) - * Lossy Image Compression Method (CS, 1-n, 3) - * Presentation LUT Shape (CS, 1, 3) - * Irradiation Event UID (CS, 1-n, 3) - * - */ + * + * Instance Number: (IS, 1, 2) + * Patient Orientation: (CS, 2, 2) + * Content Date: (DA, 1, 2C) + * Content Time: (TM, 1, 2C) + * Image Type: (CS, 1, 2-n) + * Acquisition Number (IS, 1, 3) + * Acquisition Date (DA, 1, 3) + * Acquisition Time (TM, 1, 3) + * Acquisition Date Time (DT, 1, 3) + * Image Comments (LT, 1, 3) + * Burned In Annotation (CS, 1, 3) + * Recognizable Visual Features (CS, 1, 3) + * Lossy Image Compression (CS, 1, 3) + * Lossy Image Compression Ratio (DS, 1, 3) + * Lossy Image Compression Method (CS, 1-n, 3) + * Presentation LUT Shape (CS, 1, 3) + * Irradiation Event UID (CS, 1-n, 3) + * + */ class DCMTK_DCMIOD_EXPORT IODGeneralImageModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODGeneralImageModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODGeneralImageModule(); - - /** Destructor - */ - virtual ~IODGeneralImageModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("GeneralImageModule") - */ - virtual OFString getName() const; - - /** Get Instance Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getInstanceNumber(OFString &value, - const signed long pos = 0); - - /** Get Patient Orientation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientOrientation(OFString &value, - const signed long pos = 0); - - /** Get Content Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getContentDate(OFString &value, - const signed long pos = 0); - - /** Get Content Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getContentTime(OFString &value, - const signed long pos = 0); - - /** Get Image Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageType(OFString &value, - const signed long pos = 0); - - /** Get Acquisition Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionNumber(OFString &value, - const signed long pos = 0); - - /** Get Acquisition Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionDate(OFString &value, - const signed long pos = 0); - - /** Get Acquisition Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionTime(OFString &value, - const signed long pos = 0); - - /** Get Acquisition Date Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAcquisitionDateTime(OFString &value, - const signed long pos = 0); - - /** Get Image Comments - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getImageComments(OFString &value, - const signed long pos = 0); - - /** Get Burned In Annotation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBurnedInAnnotation(OFString &value, - const signed long pos = 0); - - /** Get Recognizable Visual Features - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRecognizableVisualFeatures(OFString &value, - const signed long pos = 0); - - /** Get Lossy Image Compression - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompression(OFString &value, - const signed long pos = 0); - - /** Get Lossy Image Compression - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompressionRatio(OFString &value, - const signed long pos = 0); - - /** Get Lossy Image Compression Method - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLossyImageCompressionMethod(OFString &value, - const signed long pos = 0); - - /** Get Presentation LUT Shape - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPresentationLUTShape(OFString &value, - const signed long pos = 0); - - /** Get Irridation Event UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getIrradiationEventUID(OFString &value, - const signed long pos = 0); - - /** Set Instance Number - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setInstanceNumber(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient Orientation - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (2) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientOrientation(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Content Date - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setContentDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Content Time - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setContentTime(const OFString &value, - const OFBool checkValue = OFTrue); - - - /** Set Image Type - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (2-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImageType(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition Number - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionNumber(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition Date - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition Time - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Acquisition Date Time - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (DT) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAcquisitionDateTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Image Comments - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (LT) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setImageComments(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Burned In Annotation - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBurnedInAnnotation(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Recognizable Visual Features - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRecognizableVisualFeatures(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompression(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression Ratio - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompressionRatio(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Lossy Image Compression method - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLossyImageCompressionMethod(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Presentation LUT Shape - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPresentationLUTShape(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Irradiation Event UID - * @param value Value to be set (single value only). - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setIrradiationEventUID(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralImageModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODGeneralImageModule(); + + /** Destructor + */ + virtual ~IODGeneralImageModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("GeneralImageModule") + */ + virtual OFString getName() const; + + /** Get Instance Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceNumber(OFString& value, const signed long pos = 0); + + /** Get Patient Orientation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientOrientation(OFString& value, const signed long pos = 0); + + /** Get Content Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentDate(OFString& value, const signed long pos = 0); + + /** Get Content Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentTime(OFString& value, const signed long pos = 0); + + /** Get Image Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageType(OFString& value, const signed long pos = 0); + + /** Get Acquisition Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionNumber(OFString& value, const signed long pos = 0); + + /** Get Acquisition Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDate(OFString& value, const signed long pos = 0); + + /** Get Acquisition Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionTime(OFString& value, const signed long pos = 0); + + /** Get Acquisition Date Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDateTime(OFString& value, const signed long pos = 0); + + /** Get Image Comments + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageComments(OFString& value, const signed long pos = 0); + + /** Get Burned In Annotation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBurnedInAnnotation(OFString& value, const signed long pos = 0); + + /** Get Recognizable Visual Features + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRecognizableVisualFeatures(OFString& value, const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompression(OFString& value, const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(OFString& value, const signed long pos = 0); + + /** Get Lossy Image Compression Method + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionMethod(OFString& value, const signed long pos = 0); + + /** Get Presentation LUT Shape + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPresentationLUTShape(OFString& value, const signed long pos = 0); + + /** Get Irridation Event UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getIrradiationEventUID(OFString& value, const signed long pos = 0); + + /** Set Instance Number + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient Orientation + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (2) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientOrientation(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Content Date + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentDate(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Content Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Image Type + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (2-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageType(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition Number + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition Date + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDate(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Acquisition Date Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDateTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Image Comments + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (LT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageComments(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Burned In Annotation + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBurnedInAnnotation(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Recognizable Visual Features + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRecognizableVisualFeatures(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompression(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Ratio + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionRatio(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression method + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionMethod(const OFString& value, const OFBool checkValue = OFTrue); + + /** Helper method to set lossy compression flag of the to "01" as well as ratios + * and methods in one go. + * @param ratios Compression ratios (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. + * @param methods Methods (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. + * @param checkValues If OFTrue, the data provided is checked for validity + * @return EC_Normal if lossy compression info could be set, error code otherwise + */ + virtual OFCondition + setLossyImageCompressionFlag(const OFString& ratios, const OFString& methods, const OFBool checkValues = OFTrue); + + /** Set Presentation LUT Shape + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPresentationLUTShape(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Irradiation Event UID + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setIrradiationEventUID(const OFString& value, const OFBool checkValue = OFTrue); private: - - /// The module's name ("GeneralIamgeModule") - static const OFString m_ModuleName; + /// The module's name ("GeneralIamgeModule") + static const OFString m_ModuleName; }; #endif // MODGENERALIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h b/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h index 38d16535..c6781b87 100644 --- a/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,9 +23,9 @@ #define MODGENERALSERIES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/dcmiod/ioddef.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modbase.h" /** Class representing the General Series Module: * @@ -46,278 +46,249 @@ class DCMTK_DCMIOD_EXPORT IODGeneralSeriesModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODGeneralSeriesModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODGeneralSeriesModule(); - - /** Destructor - */ - virtual ~IODGeneralSeriesModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Set missing values by inventing "default values". Automatically - * called during write() by IODComponent. - */ - virtual void inventMissing(); - - /** Get name of module - * @return Name of the module ("GeneralSeriesModule") - */ - virtual OFString getName() const; - - /** Make sure that the module contains a Series Instance UID, i.e.\ a new one - * is created if empty. An invalid UID is corrected if desired. - * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing - */ - virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Get Modality - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getModality(OFString &value, - const signed long pos = 0) const; - - /** Get series instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Get Series Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesNumber(OFString &value, - const signed long pos = 0) const; - - /** Get Laterality - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getLaterality(OFString &value, - const signed long pos = 0) const; - - /** Get Series Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesDate(OFString &value, - const signed long pos = 0) const; - - /** Get Series Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesTime(OFString &value, - const signed long pos = 0) const; - - /** Get Performing Physician's Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPerformingPhysicianName(OFString &value, - const signed long pos = 0) const; - - /** Get Protocol Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getProtocolName(OFString &value, - const signed long pos = 0) const; - - /** Get Series Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesDescription(OFString &value, - const signed long pos = 0) const; - - /** Get Operators' Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getOperatorsName(OFString &value, - const signed long pos = 0) const; - - /** Get Body Part Examined - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBodyPartExamined(OFString &value, - const signed long pos = 0) const; - - /** Get Patient Position - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientPosition(OFString &value, - const signed long pos = 0) const; - - /** Get reference to Referenced Performed Procedure Step - * @return Reference to PPS - */ - virtual SOPInstanceReferenceMacro& getReferencedPPS(); - - /** Set Modality - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setModality(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Series Instance UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesInstanceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Series Number - * @param value Value to be set (single value only). If an empty string is, - * passed, the value "1" is set when displaying or writing the document - * since the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesNumber(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Laterality - * @param value Value to be set - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setLaterality(const DcmIODTypes::IOD_LATERALITY value, - const OFBool checkValue = OFTrue); - - /** Set Series Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Series Time - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Performing Physician Name - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPerformingPhysicianName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Protocol Name - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setProtocolName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Series Description - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesDescription(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Operators' Name - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1-n) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setOperatorsName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Body Part Examined - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBodyPartExamined(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient Position - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientPosition(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralSeriesModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODGeneralSeriesModule(); + + /** Destructor + */ + virtual ~IODGeneralSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Get name of module + * @return Name of the module ("GeneralSeriesModule") + */ + virtual OFString getName() const; + + /** Make sure that the module contains a Series Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get Modality + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString& value, const signed long pos = 0) const; + + /** Get series instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Get Series Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesNumber(OFString& value, const signed long pos = 0) const; + + /** Get Laterality + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLaterality(OFString& value, const signed long pos = 0) const; + + /** Get Series Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesDate(OFString& value, const signed long pos = 0) const; + + /** Get Series Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesTime(OFString& value, const signed long pos = 0) const; + + /** Get Performing Physician's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPerformingPhysicianName(OFString& value, const signed long pos = 0) const; + + /** Get Protocol Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getProtocolName(OFString& value, const signed long pos = 0) const; + + /** Get Series Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesDescription(OFString& value, const signed long pos = 0) const; + + /** Get Operators' Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOperatorsName(OFString& value, const signed long pos = 0) const; + + /** Get Body Part Examined + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBodyPartExamined(OFString& value, const signed long pos = 0) const; + + /** Get Patient Position + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientPosition(OFString& value, const signed long pos = 0) const; + + /** Get reference to Referenced Performed Procedure Step + * @return Reference to PPS + */ + virtual SOPInstanceReferenceMacro& getReferencedPPS(); + + /** Set Modality + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setModality(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Series Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Series Number + * @param value Value to be set (single value only). If an empty string is, + * passed, the value "1" is set when displaying or writing the document + * since the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Laterality + * @param value Value to be set + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLaterality(const DcmIODTypes::IOD_LATERALITY value, const OFBool checkValue = OFTrue); + + /** Set Series Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesDate(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Series Time + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Performing Physician Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPerformingPhysicianName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Protocol Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setProtocolName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Series Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Operators' Name + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setOperatorsName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Body Part Examined + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBodyPartExamined(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient Position + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientPosition(const OFString& value, const OFBool checkValue = OFTrue); private: + /// The name of this module ("GeneralSeriesModule") + static const OFString m_ModuleName; - /// The name of this module ("GeneralSeriesModule") - static const OFString m_ModuleName; - - /// Referenced Performed Procedure Step Sequence - SOPInstanceReferenceMacro m_ReferencedPPS; - + /// Referenced Performed Procedure Step Sequence + SOPInstanceReferenceMacro m_ReferencedPPS; }; #endif // MODGENERALSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h b/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h index 70d289cd..c2afd4d7 100644 --- a/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,223 +23,204 @@ #define MODGENERALSTUDY_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modbase.h" /** Class representing the General Study Module: - * Notation is "Attribute Name: (VR, VM, Type)" - * - * Study Instance UID: (UI, 1, 1) - * Study Date: (DA, 1, 2) - * Study Time: (TM, 1, 2) - * Referring Physician's Name: (PN, 1, 2) - * Study ID: (SH, 1, 2) - * Accession Number: (SH, 1, 2) - * Study Description: (LO, 1, 3) - * Issuer of Accession Number Sequence: (SQ, 1, 3) - * Procedure Code Sequence: (SQ, 1-n, 3) - * Reason for Performed Procedure Code Sequence: (SQ, 1-n, 3) - */ + * Notation is "Attribute Name: (VR, VM, Type)" + * + * Study Instance UID: (UI, 1, 1) + * Study Date: (DA, 1, 2) + * Study Time: (TM, 1, 2) + * Referring Physician's Name: (PN, 1, 2) + * Study ID: (SH, 1, 2) + * Accession Number: (SH, 1, 2) + * Study Description: (LO, 1, 3) + * Issuer of Accession Number Sequence: (SQ, 1, 3) + * Procedure Code Sequence: (SQ, 1-n, 3) + * Reason for Performed Procedure Code Sequence: (SQ, 1-n, 3) + */ class DCMTK_DCMIOD_EXPORT IODGeneralStudyModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODGeneralStudyModule(OFshared_ptr item, - OFshared_ptr rules); - /** Constructor - */ - IODGeneralStudyModule(); - - /** Destructor - */ - virtual ~IODGeneralStudyModule(); - - /** Set missing values by inventing "default values". Automatically - * called during write() by IODComponent. - */ - virtual void inventMissing(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("GeneralStudyModule") - */ - virtual OFString getName() const; - - /** Clear (removes) all attributes handled by the modules of this component. - * Rules are not reset. - */ - virtual void clearData(); - - /** Read data into this module from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this module to given item - * @param destination The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Make sure that the module contains a Study Instance UID, i.e.\ a new one - * is created if empty. An invalid UID is corrected if desired. - * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing - */ - virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); - - /** Get Study Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Get Study Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyDate(OFString &value, - const signed long pos = 0) const; - - /** Get Study Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyTime(OFString &value, - const signed long pos = 0) const; - - /** Get Referring Physician's Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getReferringPhysicianName(OFString &value, - const signed long pos = 0) const; - - /** Get Study ID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyID(OFString &value, - const signed long pos = 0) const; - - /** Get Accession Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAccessionNumber(OFString &value, - const signed long pos = 0) const; - - /** Get Study Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getStudyDescription(OFString &value, - const signed long pos = 0) const; - - /** Get reference to content of Issuer of Accession Number Sequence - * @return Reference to single item of Issuer of Accession Number Sequence - */ - virtual HL7HierarchicDesignatorMacro& getIssuerOfAccesionNumber(); - - /** Get reference to content of Procedure Code Sequence - * @return Reference to items of Procedure Code Sequence - */ - virtual OFVector& getProcedureCodeSequence(); - - /** Get reference to content of Reason for Performed Procedure Code Sequence - * @return Reference to items of Procedure Code Sequence - */ - virtual OFVector& getReasonForPerformedProcedureCodeSequence(); - - /** Set Study Instance UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyInstanceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Study Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** set study time - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyTime(const OFString &value, - const OFBool checkValue = OFTrue); - /** Set Referring Physician's Name - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setReferringPhysicianName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Study ID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Accession Number - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAccessionNumber(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Study Description - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setStudyDescription(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralStudyModule(OFshared_ptr item, OFshared_ptr rules); + /** Constructor + */ + IODGeneralStudyModule(); + + /** Destructor + */ + virtual ~IODGeneralStudyModule(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("GeneralStudyModule") + */ + virtual OFString getName() const; + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Make sure that the module contains a Study Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Get Study Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Get Study Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyDate(OFString& value, const signed long pos = 0) const; + + /** Get Study Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyTime(OFString& value, const signed long pos = 0) const; + + /** Get Referring Physician's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferringPhysicianName(OFString& value, const signed long pos = 0) const; + + /** Get Study ID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyID(OFString& value, const signed long pos = 0) const; + + /** Get Accession Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAccessionNumber(OFString& value, const signed long pos = 0) const; + + /** Get Study Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyDescription(OFString& value, const signed long pos = 0) const; + + /** Get reference to content of Issuer of Accession Number Sequence + * @return Reference to single item of Issuer of Accession Number Sequence + */ + virtual HL7HierarchicDesignatorMacro& getIssuerOfAccessionNumber(); + + /** Get reference to content of Procedure Code Sequence + * @return Reference to items of Procedure Code Sequence + */ + virtual OFVector& getProcedureCodeSequence(); + + /** Get reference to content of Reason for Performed Procedure Code Sequence + * @return Reference to items of Procedure Code Sequence + */ + virtual OFVector& getReasonForPerformedProcedureCodeSequence(); + + /** Set Study Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Study Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyDate(const OFString& value, const OFBool checkValue = OFTrue); + + /** set study time + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyTime(const OFString& value, const OFBool checkValue = OFTrue); + /** Set Referring Physician's Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferringPhysicianName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Study ID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Accession Number + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAccessionNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Study Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyDescription(const OFString& value, const OFBool checkValue = OFTrue); private: + /// Name of this module ("GeneralStudyModule") + static const OFString m_ModuleName; - /// Name of this module ("GeneralStudyModule") - static const OFString m_ModuleName; - - /// Issuer of Accession Number Sequence - HL7HierarchicDesignatorMacro m_IssuerOfAccessionNumberSequence; - - /// Procedure Code Sequence - OFVector m_ProcedureCodeSequence; + /// Issuer of Accession Number Sequence + HL7HierarchicDesignatorMacro m_IssuerOfAccessionNumberSequence; - /// Reason for Performed Procedure Code Sequence - OFVector m_ReasonForPerformedProcedureCodeSequence; + /// Procedure Code Sequence + OFVector m_ProcedureCodeSequence; + /// Reason for Performed Procedure Code Sequence + OFVector m_ReasonForPerformedProcedureCodeSequence; }; #endif // MODGENERALSTUDY_H diff --git a/dcmiod/include/dcmtk/dcmiod/modhelp.h b/dcmiod/include/dcmtk/dcmiod/modhelp.h index 5853f506..f7b22852 100644 --- a/dcmiod/include/dcmtk/dcmiod/modhelp.h +++ b/dcmiod/include/dcmtk/dcmiod/modhelp.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -22,7 +22,7 @@ #ifndef MODHELP_H #define MODHELP_H -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/ofstd/oftypes.h" #include "dcmtk/dcmiod/ioddef.h" @@ -30,20 +30,22 @@ class DcmTagKey; class DcmItem; - /** This class contains helper functions that permit copying common modules * from DICOM standard part 3 between DICOM datasets. * @note The attribute lists per module are taken from the final text version * of DICOM 2013. */ -class DCMTK_DCMIOD_EXPORT DcmModuleHelpers { - - protected: - - /// Generic copy module helper method. - template - static inline void copyModule(const DcmTagKey (&tags)[N], - DcmItem& src, DcmItem& dest); +class DCMTK_DCMIOD_EXPORT DcmModuleHelpers +{ + +protected: + /** Generic copy module helper method. + * @param tags Reference of array with tags to be copied + * @param src The source item to read the attributes from + * @param dest The target item to write the attributes to + */ + template + static inline void copyModule(const DcmTagKey (&tags)[N], DcmItem& src, DcmItem& dest); /// List of tags within the Patient Module static const DcmTagKey patientModuleTags[]; @@ -79,8 +81,7 @@ class DCMTK_DCMIOD_EXPORT DcmModuleHelpers { /// List of tags within the General Image Module static const DcmTagKey generalImageModuleTags[]; - public: - +public: /** Copy element defined by tag from source item to destination item. * No in-depth search is performed but only the main level is searched * for the given tag. If the tag is not found, the destination item diff --git a/dcmiod/include/dcmtk/dcmiod/modimagepixel.h b/dcmiod/include/dcmtk/dcmiod/modimagepixel.h index 281edf59..48a179e3 100644 --- a/dcmiod/include/dcmtk/dcmiod/modimagepixel.h +++ b/dcmiod/include/dcmtk/dcmiod/modimagepixel.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,8 @@ #define MODIMAGEPIXEL_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/modimagepixelbase.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/modimagepixelbase.h" /** Class representing the Image Pixel Module: * @@ -41,175 +41,158 @@ * Pixel Aspect Ratio: (IS, 2, 1C) * ICC Profile: (OB, 1, 3) */ -template +template class DCMTK_DCMIOD_EXPORT IODImagePixelModule : public IODImagePixelBase { public: - - /// Data type of pixels - typedef T value_type; - - static const DcmTagKey pixel_data_tag; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODImagePixelModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODImagePixelModule(); - - /** Destructor - */ - virtual ~IODImagePixelModule(); - - /** Read attributes from given item into this class - * @param source The source to read from - * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise - * old data is overwritten (or amended) - * @result EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write attributes from this class into given item - * @param destination The item to write to - * @result EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("ImagePixelModule") - */ - virtual OFString getName() const; - - /** Get pixel data type, always returns DataType::INTEGER for this class. - * @return The data type of the pixel data - */ - virtual DataType getDataType() const; - - /** Get Bits Stored - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBitsStored(Uint16& value, - const signed long pos = 0); - - /** Get High Bit - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getHighBit(Uint16& value, - const signed long pos = 0); - - /** Get Pixel Representation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPixelRepresentation(Uint16& value, - const signed long pos = 0); - - /** Get Planar Configuration - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPlanarConfiguration(Uint16& value, - const signed long pos = 0); - - /** Get ICC Profile - * @param values Reference to variable in which the values should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getICCProfile(OFVector& values); - - /** Set Samples per Pixel - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (US) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSamplesPerPixel(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Photometric Interpretation - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPhotometricInterpretation(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Bits Allocated - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBitsAllocated(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Bits Stored - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setBitsStored(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set High Bit - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setHighBit(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Pixel Representation - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (US) and consistency - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPixelRepresentation(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Planar Configuration - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value' for conformance with VR (US) and consistency - * with other attributes if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPlanarConfiguration(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set ICC Profile - * @param values Reference to variable in which the values should be stored - * @param length Length of array provided in values parameter - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setICCProfile(const Uint8* values, - const size_t length); + /// Data type of pixels + typedef T value_type; + + static const DcmTagKey pixel_data_tag; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODImagePixelModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODImagePixelModule(); + + /** Destructor + */ + virtual ~IODImagePixelModule(); + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("ImagePixelModule") + */ + virtual OFString getName() const; + + /** Get pixel data type, always returns DataType::INTEGER for this class. + * @return The data type of the pixel data + */ + virtual DataType getDataType() const; + + /** Get Bits Stored + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsStored(Uint16& value, const unsigned long pos = 0); + + /** Get High Bit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getHighBit(Uint16& value, const unsigned long pos = 0); + + /** Get Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelRepresentation(Uint16& value, const unsigned long pos = 0); + + /** Get Planar Configuration + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPlanarConfiguration(Uint16& value, const unsigned long pos = 0); + + /** Get ICC Profile + * @param values Reference to variable in which the values should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getICCProfile(OFVector& values); + + /** Set Samples per Pixel + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSamplesPerPixel(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPhotometricInterpretation(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsAllocated(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Bits Stored + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsStored(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set High Bit + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setHighBit(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelRepresentation(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Planar Configuration + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPlanarConfiguration(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set ICC Profile + * @param values Reference to variable in which the values should be stored + * @param length Length of array provided in values parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setICCProfile(const Uint8* values, const size_t length); private: - - /// This module's name ("ImagePixelModule") - static const OFString m_ModuleName; - + /// This module's name ("ImagePixelModule") + static const OFString m_ModuleName; }; #endif // MODIMAGEPIXEL_H diff --git a/dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h b/dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h index 7455e020..c1cc2dd7 100644 --- a/dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h +++ b/dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -15,7 +15,7 @@ * * Author: Michael Onken * - * Purpose: Base class for Image Pixel Module and related (e.g. Ploating Point) + * Purpose: Base class for Image Pixel Module and related (e.g. Floating Point) * */ @@ -32,137 +32,124 @@ class DCMTK_DCMIOD_EXPORT IODImagePixelBase : public IODModule { public: - enum DataType { - DATA_TYPE_UNKNOWN, - DATA_TYPE_FLOAT, - DATA_TYPE_DOUBLE, - DATA_TYPE_INTEGER + DATA_TYPE_UNKNOWN, + DATA_TYPE_FLOAT, + DATA_TYPE_DOUBLE, + DATA_TYPE_INTEGER }; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODImagePixelBase(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODImagePixelBase(); - - /** Destructor - */ - virtual ~IODImagePixelBase(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("ImagePixelModule") - */ - virtual OFString getName() const; - - /** Get pixel data type - * @return The data type of the pixel data - */ - virtual DataType getDataType() const = 0; - - // ------------------------------------------------------------------------- - // Getters for all attribute that appear in all Image Pixel Modules - // ------------------------------------------------------------------------- - - /** Get Samples per Pixel - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSamplesPerPixel(Uint16 &value, - const signed long pos = 0); - - /** Get Photometric Interpretation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPhotometricInterpretation(OFString&value, - const signed long pos = 0); - - /** Get Rows - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRows(Uint16& value, - const signed long pos = 0); - - /** Get Columns - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getColumns(Uint16& value, - const signed long pos = 0); - - /** Get Bits Allocated - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getBitsAllocated(Uint16& value, - const signed long pos = 0); - - /** Get Pixel Aspect Ratio - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPixelAspectRatio(Uint16& value, - const signed long pos = 0); - - // ------------------------------------------------------------------------- - // Setters for all attribute that appear in all Image Pixel Modules and which - // do not have fixed values in sub classes. - // ------------------------------------------------------------------------- - - /** Set Rows - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRows(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Columns - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setColumns(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Pixel Aspect Ratio - * @param verticalPixelSize The vertical pixel size (no unit) - * @param horizontalPixelSize The horizontal pixel size (no unit) - * @param checkValue Check 'value' for conformance with VR (IS) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPixelAspectRatio(const OFString& verticalPixelSize, - const OFString& horizontalPixelSize, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODImagePixelBase(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODImagePixelBase(); + + /** Destructor + */ + virtual ~IODImagePixelBase(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("ImagePixelModule") + */ + virtual OFString getName() const; + + /** Get pixel data type + * @return The data type of the pixel data + */ + virtual DataType getDataType() const = 0; + + // ------------------------------------------------------------------------- + // Getters for all attribute that appear in all Image Pixel Modules + // ------------------------------------------------------------------------- + + /** Get Samples per Pixel + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSamplesPerPixel(Uint16& value, const unsigned long pos = 0); + + /** Get Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPhotometricInterpretation(OFString& value, const signed long pos = 0); + + /** Get Rows + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRows(Uint16& value, const unsigned long pos = 0); + + /** Get Columns + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getColumns(Uint16& value, const unsigned long pos = 0); + + /** Get Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsAllocated(Uint16& value, const unsigned long pos = 0); + + /** Get Pixel Aspect Ratio + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelAspectRatio(Uint16& value, const unsigned long pos = 0); + + // ------------------------------------------------------------------------- + // Setters for all attribute that appear in all Image Pixel Modules and which + // do not have fixed values in sub classes. + // ------------------------------------------------------------------------- + + /** Set Rows + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRows(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Columns + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setColumns(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Pixel Aspect Ratio + * @param verticalPixelSize The vertical pixel size (no unit) + * @param horizontalPixelSize The horizontal pixel size (no unit) + * @param checkValue Check 'value' for conformance with VR (IS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelAspectRatio(const OFString& verticalPixelSize, + const OFString& horizontalPixelSize, + const OFBool checkValue = OFTrue); private: - - /// This module's name ("ImagePixelBase") - static const OFString m_ModuleName; - + /// This module's name ("ImagePixelBase") + static const OFString m_ModuleName; }; #endif // MODIMAGEPIXELBASE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h b/dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h index c4adb545..f06a92ea 100644 --- a/dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h +++ b/dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2017, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -24,31 +24,30 @@ #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofvriant.h" #include "dcmtk/dcmiod/modimagepixelbase.h" - +#include "dcmtk/ofstd/ofvriant.h" /** Visitor for returning base class of given Image Pixel Module */ struct IODImagePixelVariantBaseVisitor { - /** Returns NULL since given argument is no pixel module at all - * @return OFnullptr - */ - IODImagePixelBase* operator()( OFmonostate& ) - { - return OFnullptr; - } - - /** Returns the base class pointer of all pixel modules - * @param base IODImagePixelBase pointer to given class instance - * @return OFnullptr - */ - IODImagePixelBase* operator()( IODImagePixelBase& base ) - { - return &base; - } + /** Returns NULL since given argument is no pixel module at all + * @return OFnullptr + */ + IODImagePixelBase* operator()(OFmonostate&) + { + return OFnullptr; + } + + /** Returns the base class pointer of all pixel modules + * @param base IODImagePixelBase pointer to given class instance + * @return OFnullptr + */ + IODImagePixelBase* operator()(IODImagePixelBase& base) + { + return &base; + } }; /** Class representing different pixel modules from the DICOM standard: @@ -56,226 +55,208 @@ struct IODImagePixelVariantBaseVisitor * and the Double Floating Point Image Pixel module */ #ifdef HAVE_CXX11 -template -class IODImagePixelVariant -: public OFvariant +template +class IODImagePixelVariant : public OFvariant #else -template -class IODImagePixelVariant -: public OFvariant +template +class IODImagePixelVariant : public OFvariant #endif { public: - - /** Constructor - */ - IODImagePixelVariant() - : IODImagePixelVariant::variant() - { - - } - - /** Constructor, constructs pixel module based on given type - */ - template - IODImagePixelVariant(const T& t) - : IODImagePixelVariant::variant(t) - { - - } - - /** Destructor - */ - ~IODImagePixelVariant() - { - - } - - /** Get name of module - * @return Name of the actual module (e.g. "ImagePixelModule") - */ - OFString getName() const - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getName(); - return OFString(); - } - - /** Get pixel data type - * @return The data type of the pixel data - */ - IODImagePixelBase::DataType getDataType() const - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getDataType(); - return IODImagePixelBase::DATA_TYPE_UNKNOWN; - } - - /** Clear data (base class version) - */ - void clearData() - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - pBase->clearData(); - } - - // ------------------------------------------------------------------------- - // Getters for all attribute that appear in all Image Pixel Modules - // ------------------------------------------------------------------------- - - /** Get Samples per Pixel - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getSamplesPerPixel(Uint16 &value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getSamplesPerPixel(value, pos); - return IOD_EC_InvalidPixelData; - } - - /** Get Photometric Interpretation - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getPhotometricInterpretation(OFString&value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getPhotometricInterpretation(value, pos); - return IOD_EC_InvalidPixelData; - } - - /** Get Rows - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getRows(Uint16& value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getRows(value, pos); - return IOD_EC_InvalidPixelData; - } - - /** Get Columns - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getColumns(Uint16& value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getColumns(value, pos); - return IOD_EC_InvalidPixelData; - } - - /** Get Bits Allocated - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getBitsAllocated(Uint16& value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getBitsAllocated(value, pos); - return IOD_EC_InvalidPixelData; - } - - /** Get Pixel Aspect Ratio - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition getPixelAspectRatio(Uint16& value, - const signed long pos = 0) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->getPixelAspectRatio(value, pos); - return IOD_EC_InvalidPixelData; - } - - // ------------------------------------------------------------------------- - // Setters for all attribute that appear in all Image Pixel Modules and which - // do not have fixed values in sub classes. - // ------------------------------------------------------------------------- - - /** Set Rows - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition setRows(const Uint16 value, - const OFBool checkValue = OFTrue) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->setRows(value, checkValue); - return IOD_EC_InvalidPixelData; - - } - - /** Set Columns - * @param value Reference to variable in which the value should be stored - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition setColumns(const Uint16 value, - const OFBool checkValue = OFTrue) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->setColumns(value, checkValue); - return IOD_EC_InvalidPixelData; - - } - - /** Set Pixel Aspect Ratio - * @param verticalPixelSize The vertical pixel size (no unit) - * @param horizontalPixelSize The horizontal pixel size (no unit) - * @param checkValue Check 'value' for conformance with VR (IS) - * @return EC_Normal if successful, an error code otherwise - */ - OFCondition setPixelAspectRatio(const OFString& verticalPixelSize, - const OFString& horizontalPixelSize, - const OFBool checkValue = OFTrue) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->setPixelAspectRatio(verticalPixelSize, horizontalPixelSize, checkValue); - return IOD_EC_InvalidPixelData; - - } - - /** Write pixel module base class data to given item - * @param dataset The item to write to (usually dataset level) - * @return EC_Normal if successful, error otherwise - */ - OFCondition write(DcmItem& dataset) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->write(dataset); - return IOD_EC_InvalidPixelData; - - } - - /** Read pixel module base class data from given item - * @param dataset The item to read from (usually dataset level) - * @return EC_Normal if successful, error otherwise - */ - OFCondition read(DcmItem& dataset) - { - if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) - return pBase->read(dataset); - return IOD_EC_InvalidPixelData; - } - + /** Constructor + */ + IODImagePixelVariant() + : IODImagePixelVariant::variant() + { + } + + /** Constructor, constructs pixel module based on given type + * @param t The Image Pixel Module to be used + */ + template + IODImagePixelVariant(const T& t) + : IODImagePixelVariant::variant(t) + { + } + + /** Destructor + */ + ~IODImagePixelVariant() + { + } + + /** Get name of module + * @return Name of the actual module (e.g. "ImagePixelModule") + */ + OFString getName() const + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getName(); + return OFString(); + } + + /** Get pixel data type + * @return The data type of the pixel data + */ + IODImagePixelBase::DataType getDataType() const + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getDataType(); + return IODImagePixelBase::DATA_TYPE_UNKNOWN; + } + + /** Clear data (base class version) + */ + void clearData() + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + pBase->clearData(); + } + + // ------------------------------------------------------------------------- + // Getters for all attribute that appear in all Image Pixel Modules + // ------------------------------------------------------------------------- + + /** Get Samples per Pixel + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getSamplesPerPixel(Uint16& value, const unsigned long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getSamplesPerPixel(value, pos); + return IOD_EC_InvalidPixelData; + } + + /** Get Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getPhotometricInterpretation(OFString& value, const signed long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getPhotometricInterpretation(value, pos); + return IOD_EC_InvalidPixelData; + } + + /** Get Rows + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getRows(Uint16& value, const unsigned long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getRows(value, pos); + return IOD_EC_InvalidPixelData; + } + + /** Get Columns + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getColumns(Uint16& value, const unsigned long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getColumns(value, pos); + return IOD_EC_InvalidPixelData; + } + + /** Get Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getBitsAllocated(Uint16& value, const unsigned long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getBitsAllocated(value, pos); + return IOD_EC_InvalidPixelData; + } + + /** Get Pixel Aspect Ratio + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getPixelAspectRatio(Uint16& value, const unsigned long pos = 0) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->getPixelAspectRatio(value, pos); + return IOD_EC_InvalidPixelData; + } + + // ------------------------------------------------------------------------- + // Setters for all attribute that appear in all Image Pixel Modules and which + // do not have fixed values in sub classes. + // ------------------------------------------------------------------------- + + /** Set Rows + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition setRows(const Uint16 value, const OFBool checkValue = OFTrue) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->setRows(value, checkValue); + return IOD_EC_InvalidPixelData; + } + + /** Set Columns + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition setColumns(const Uint16 value, const OFBool checkValue = OFTrue) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->setColumns(value, checkValue); + return IOD_EC_InvalidPixelData; + } + + /** Set Pixel Aspect Ratio + * @param verticalPixelSize The vertical pixel size (no unit) + * @param horizontalPixelSize The horizontal pixel size (no unit) + * @param checkValue Check 'value' for conformance with VR (IS) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition setPixelAspectRatio(const OFString& verticalPixelSize, + const OFString& horizontalPixelSize, + const OFBool checkValue = OFTrue) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->setPixelAspectRatio(verticalPixelSize, horizontalPixelSize, checkValue); + return IOD_EC_InvalidPixelData; + } + + /** Write pixel module base class data to given item + * @param dataset The item to write to (usually dataset level) + * @return EC_Normal if successful, error otherwise + */ + OFCondition write(DcmItem& dataset) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->write(dataset); + return IOD_EC_InvalidPixelData; + } + + /** Read pixel module base class data from given item + * @param dataset The item to read from (usually dataset level) + * @return EC_Normal if successful, error otherwise + */ + OFCondition read(DcmItem& dataset) + { + if (IODImagePixelBase* pBase = OFvisit(IODImagePixelVariantBaseVisitor(), *this)) + return pBase->read(dataset); + return IOD_EC_InvalidPixelData; + } }; #endif // MODIMAGEPIXELBASE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h b/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h index 83ff45ed..ac8fcd8a 100644 --- a/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h +++ b/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -47,340 +47,312 @@ class DCMTK_DCMIOD_EXPORT IODMultiframeDimensionModule : public IODModule { public: - - /** Helper class representing an item within the Dimension Index Sequence, - * i.e.\ a single dimension description - */ - class DimensionOrganizationItem : public IODComponent - { - - public: - - /** Constructor - * @param data The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - DimensionOrganizationItem(OFshared_ptr data, - OFshared_ptr rules, - IODComponent* parent); - - /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) - */ - DimensionOrganizationItem(IODComponent* parent = NULL); - - /** Destructor - */ - virtual ~DimensionOrganizationItem(); - - /** Get name of module ("DimensionIndexPointerSequence") - * @return Name of the module ("DimensionIndexPointerSequence") - */ - virtual OFString getName() const; - - /** Resets rules of this module to their original values + /** Helper class representing an item within the Dimension Index Sequence, + * i.e.\ a single dimension description */ - virtual void resetRules(); - - /** Get Dimension Organization UID - * @param value Reference to variable in which the value should be - * stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + class DCMTK_DCMIOD_EXPORT DimensionOrganizationItem : public IODComponent + { + + public: + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionOrganizationItem(OFshared_ptr data, OFshared_ptr rules, IODComponent* parent); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionOrganizationItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~DimensionOrganizationItem(); + + /** Get name of module ("DimensionIndexPointerSequence") + * @return Name of the module ("DimensionIndexPointerSequence") + */ + virtual OFString getName() const; + + /** Resets rules of this module to their original values + */ + virtual void resetRules(); + + /** Get Dimension Organization UID + * @param value Reference to variable in which the value should be + * stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationUID(OFString& value, const signed long pos = 0) const; + + /** Set Dimension Organization UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationUID(const OFString& value, const OFBool checkValue = OFTrue); + }; + + /** Class representing a Dimension Index Pointer Sequence Item + * managed by the Multi-frame Dimension Module */ - virtual OFCondition getDimensionOrganizationUID(OFString &value, - const signed long pos = 0) const; - - /** Set Dimension Organization UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled - * @return status EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDimensionOrganizationUID(const OFString& value, - const OFBool checkValue = OFTrue); - }; - - /** Class representing a Dimension Index Pointer Sequence Item - * managed by the Multi-frame Dimension Module - */ - class DimensionIndexItem : public IODComponent - { - - public: + class DimensionIndexItem : public IODComponent + { + + public: + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionIndexItem(OFshared_ptr data, OFshared_ptr rules, IODComponent* parent); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionIndexItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~DimensionIndexItem(); + + /** Get name of module ("DimensionIndexSequence") + * @return Name of the module ("[parent.]DimensionIndexSequence") + */ + virtual OFString getName() const; + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get Dimension Index Pointer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionIndexPointer(DcmTagKey& value, const signed long pos = 0) const; + + /** Get Dimension Index Private Creator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionIndexPrivateCreator(OFString& value, const signed long pos = 0) const; + + /** Get Functional Group Pointer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFunctionalGroupPointer(DcmTagKey& value, const signed long pos = 0) const; + + /** Get Functional Group Private Creator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFunctionalGroupPrivateCreator(OFString& value, const signed long pos = 0) const; + + /** Get Dimension Organization UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationUID(OFString& value, const signed long pos = 0) const; + + /** Get Dimension Description Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionDescriptionLabel(OFString& value, const signed long pos = 0) const; + + /** Set Dimension Index Pointer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionIndexPointer(const DcmTagKey& value, const OFBool checkValue = OFTrue); + + /** Set Dimension Index Private Creator + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionIndexPrivateCreator(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Dimension Index Functional Group Pointer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFunctionalGroupPointer(const DcmTagKey& value, const OFBool checkValue = OFTrue); + + /** Set Dimension Index Functional Group Private Creator + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value. Not evaluated (here for consistency + * with other setter functions). + * + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFunctionalGroupPrivateCreator(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Dimension Organization UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Dimension Description Label + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionDescriptionLabel(const OFString& value, const OFBool checkValue = OFTrue); + }; /** Constructor - * @param data The item to be used for data storage. If NULL, the + * @param item The item to be used for data storage. If NULL, the * class creates an empty data container. * @param rules The rule set for this class. If NULL, the class creates * one from scratch and adds its values. - * @param parent The parent of the IOD component (NULL if none or unknown) */ - DimensionIndexItem(OFshared_ptr data, - OFshared_ptr rules, - IODComponent* parent); + IODMultiframeDimensionModule(OFshared_ptr item, OFshared_ptr rules); /** Constructor - * @param parent The parent of the IOD component (NULL if none or unknown) */ - DimensionIndexItem(IODComponent* parent = NULL); + IODMultiframeDimensionModule(); /** Destructor */ - virtual ~DimensionIndexItem(); - - /** Get name of module ("DimensionIndexSequence") - * @return Name of the module ("[parent.]DimensionIndexSequence") - */ - virtual OFString getName() const; - - /** Resets rules to their original values + virtual ~IODMultiframeDimensionModule(); + + /** Convenience method to add Dimension Index. + * @param dimensionIndexPointer The Dimension Index Pointer attribute + * @param dimensionOrganizationUID The Dimension Organization UID of the dimension organization + * the pointer refers to. If UID does not exist yet (in the Dimension + * Organization Sequence, it is created there automatically). + * @param functionalGroupPointer The functional group where the pointer attribute can be found + * @param dimensionDescriptionLabel The description label of this dimension (optional) + * @param dimensionIndexPrivateCreator The private creator of the Dimension Index Pointer + * attribute. Required if dimensionIndexPointer points to a private attribute tag. + * @param functionalGroupPrivateCreator The private creator of the functional group. Required + * if functionalGroupPointer points to a private attribute tag. + * @return EC_Normal if index could be added, error otherwise (basic parameter checking) + * */ - virtual void resetRules(); - - /** Get Dimension Index Pointer - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + virtual OFCondition addDimensionIndex(const DcmTagKey& dimensionIndexPointer, + const OFString& dimensionOrganizationUID, + const DcmTagKey& functionalGroupPointer, + const OFString& dimensionDescriptionLabel = "", + const OFString& dimensionIndexPrivateCreator = "", + const OFString& functionalGroupPrivateCreator = ""); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. */ - virtual OFCondition getDimensionIndexPointer(DcmTagKey &value, - const signed long pos = 0) const; + virtual void clearData(); - /** Get Dimension Index Private Creator - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise */ - virtual OFCondition getDimensionIndexPrivateCreator(OFString& value, - const signed long pos = 0) const; + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); - /** Get Functional Group Pointer - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise */ - virtual OFCondition getFunctionalGroupPointer(DcmTagKey &value, - const signed long pos = 0) const; + virtual OFCondition write(DcmItem& destination); - /** Get Functional Group Private Creator - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + /** Resets rules to their original values. */ - virtual OFCondition getFunctionalGroupPrivateCreator(OFString &value, - const signed long pos = 0) const; + virtual void resetRules(); - /** Get Dimension Organization UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + /** Get name of module ("MultiframeDimensionModule") + * @return Name of the module ("MultiframeDimensionModule") */ - virtual OFCondition getDimensionOrganizationUID(OFString &value, - const signed long pos = 0) const; + virtual OFString getName() const; - /** Get Dimension Description Label + /** Get Dimension Organization Type * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getDimensionDescriptionLabel(OFString &value, - const signed long pos = 0) const; - - /** Set Dimension Index Pointer - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return status EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDimensionIndexPointer(const DcmTagKey&value, - const OFBool checkValue = OFTrue); + virtual OFCondition getDimensionOrganizationType(OFString& value, const signed long pos = 0) const; - /** Set Dimension Index Private Creator + /** Set Dimension Organization Type (Defined Terms as of DICOM 2014a "3D" and "3D_TEMPORAL") * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @param checkValue Check 'value' for conformance with VR and VM if enabled * @return status EC_Normal if successful, an error code otherwise */ - virtual OFCondition setDimensionIndexPrivateCreator(const OFString& value, - const OFBool checkValue = OFTrue); + virtual OFCondition setDimensionOrganizationType(const OFString& value, const OFBool checkValue = OFTrue); - /** Set Dimension Index Functional Group Pointer - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return status EC_Normal if successful, an error code otherwise + /** Get content of the Dimension Index Sequence + * @return Reference to the Dimension Index Pointer Sequence */ - virtual OFCondition setFunctionalGroupPointer(const DcmTagKey& value, - const OFBool checkValue = OFTrue); + virtual OFVector& getDimensionIndexSequence(); - /** Set Dimension Index Functional Group Private Creator - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value. Not evaluated (here for consistency - * with other setter functions). - * - * @return status EC_Normal if successful, an error code otherwise + /** Get content of the Dimension Organization Sequence + * @return Reference to the Dimension Organization Sequence */ - virtual OFCondition setFunctionalGroupPrivateCreator(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Dimension Organization UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR and VM if enabled - * @return status EC_Normal if successful, an error code otherwise + virtual OFVector& getDimensionOrganizationSequence(); + + /** Check dimensions for consistency with functional groups. Note that one can provide + * an item that provides the dataset containing the functional groups to check against. + * This item must contain on main level the Shared and Per-frame Functional Group + * Sequence. If no item is given (NULL pointer) it is tried to find these sequences + * within "this" object which works in the case that this class was initialized with + * an existing item (or the fg data was inserted in another way afterwards). + * @param fgItem The item containing functional group information + * @return EC_Normal, if consistency is fine, error otherwise */ - virtual OFCondition setDimensionOrganizationUID(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Dimension Description Label - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR and VM if enabled - * @return status EC_Normal if successful, an error code otherwise + virtual OFCondition checkDimensions(DcmItem* fgItem = NULL); + + /** Get specific index pointer element from per-frame functional group + * sequence. Prints out error messages if index does not exist or + * index location information provided by parameters is incomplete or invalid + * @param perFrameFG An instance of the Per-Frame Functional Group Sequence that + * should be searched + * @param fgPointer The tag key of the functional group the value resides in + * @param indexPointer The tag of the dimension value inside the functional group + * @param fgPrivateCreator The private creator of the fgPointer tag key. Only required + * if fgPointer is a private tag key (odd element number) + * @param privateCreator The private creator of the indexPointer tag key. Only required + * if indexPointer is a private tag key (odd element number) + * @return The element pointed to. If element could not be located, NULL is returned. */ - virtual OFCondition setDimensionDescriptionLabel(const OFString& value, - const OFBool checkValue = OFTrue); - }; - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODMultiframeDimensionModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODMultiframeDimensionModule(); - - /** Destructor - */ - virtual ~IODMultiframeDimensionModule(); - - /** Convenience method to add Dimension Index. - * @param dimensionIndexPointer The Dimension Index Pointer attribute - * @param dimensionOrganizationUID The Dimension Organization UID of the dimension organization - * the pointer refers to. If UID does not exist yet (in the Dimension - * Organization Sequence, it is created there automatically). - * @param functionalGroupPointer The functional group where the pointer attribute can be found - * @param dimensionDescriptionLabel The description label of this dimension (optional) - * @param dimensionIndexPrivateCreator The private creator of the Dimension Index Pointer - * attribute. Required if dimensionIndexPointer points to a private attribute tag. - * @param functionalGroupPrivateCreator The private creator of the functional group. Required - * if functionalGroupPointer points to a private attribute tag. - * @return EC_Normal if index could be added, error otherwise (basic parameter checking) - * - */ - virtual OFCondition addDimensionIndex(const DcmTagKey& dimensionIndexPointer, - const OFString& dimensionOrganizationUID, - const DcmTagKey& functionalGroupPointer, - const OFString& dimensionDescriptionLabel = "", - const OFString& dimensionIndexPrivateCreator = "", - const OFString& functionalGroupPrivateCreator = ""); - - /** Clear (removes) all attributes handled by the modules of this component. - * Rules are not reset. - */ - virtual void clearData(); - - /** Read data into this module from given item - * @param source The item to read from - * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& source, - const OFBool clearOldData = OFTrue); - - /** Write this module to given item - * @param destination The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& destination); - - /** Resets rules to their original values. - */ - virtual void resetRules(); - - /** Get name of module ("MultiframeDimensionModule") - * @return Name of the module ("MultiframeDimensionModule") - */ - virtual OFString getName() const; - - /** Get Dimension Organization Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getDimensionOrganizationType(OFString &value, - const signed long pos = 0) const; - - /** Set Dimension Organization Type (Defined Terms as of DICOM 2014a "3D" and "3D_TEMPORAL") - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR and VM if enabled - * @return status EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setDimensionOrganizationType(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Get content of the Dimension Index Sequence - * @return Reference to the Dimension Index Pointer Sequence - */ - virtual OFVector& getDimensionIndexSequence(); - - /** Get content of the Dimension Organization Sequence - * @return Reference to the Dimension Organization Sequence - */ - virtual OFVector& getDimensionOrganizationSequence(); - - - /** Check dimensions for consistency with functional groups. Note that one can provide - * an item that provides the dataset containing the functional groups to check against. - * This item must contain on main level the Shared and Per-frame Functional Group - * Sequence. If no item is given (NULL pointer) it is tried to find these sequences - * within "this" object which works in the case that this class was initialized with - * an existing item (or the fg data was inserted in another way afterwards). - * @param fgItem The item containing functional group information - * @return EC_Normal, if consistency is fine, error otherwise - */ - virtual OFCondition checkDimensions(DcmItem* fgItem = NULL); - - /** Get specific index pointer element from per-frame functional group - * sequence. Prints out error messages if index does not exist or - * index location information provided by parameters is incomplete or invalid - * @param perFrameFG An instance of the Per-Frame Functional Group Sequence that - * should be searched - * @param fgPointer The tag key of the functional group the value resides in - * @param indexPointer The tag of the dimension value inside the functional group - * @param fgPrivateCreator The private creator of the fgPointer tag key. Only required - * if fgPointer is a private tag key (odd element number) - * @param privateCreator The private creator of the indexPointer tag key. Only required - * if indexPointer is a private tag key (odd element number) - * @return The element pointed to. If element could not be located, NULL is returned. - */ - virtual DcmElement* getIndexElement(DcmSequenceOfItems* perFrameFG, - const DcmTagKey& fgPointer, - const DcmTagKey& indexPointer, - const OFString& fgPrivateCreator, - const OFString& privateCreator); + virtual DcmElement* getIndexElement(DcmSequenceOfItems* perFrameFG, + const DcmTagKey& fgPointer, + const DcmTagKey& indexPointer, + const OFString& fgPrivateCreator, + const OFString& privateCreator); protected: - - /** Go over Dimension Index Pointers and extract Dimension Organization UIDs for - * Dimension Organization Sequence. - */ - void createDimensionOrganizationData(); + /** Go over Dimension Index Pointers and extract Dimension Organization UIDs for + * Dimension Organization Sequence. + */ + void createDimensionOrganizationData(); private: + /// This module's name (MultiframeDimensionModule) + static const OFString m_ModuleName; - /// This module's name (MultiframeDimensionModule) - static const OFString m_ModuleName; - - /// Vector with all items of the Dimension Index Pointer Sequence - OFVector m_DimensionIndexSequence; + /// Vector with all items of the Dimension Index Pointer Sequence + OFVector m_DimensionIndexSequence; - /// Vector with all items of the Dimension Organization Sequence - OFVector m_DimensionOrganizationSequence; + /// Vector with all items of the Dimension Organization Sequence + OFVector m_DimensionOrganizationSequence; }; #endif // MODMULTIFRAMEDIMENSION_H diff --git a/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h b/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h index 213db6d8..65f79ee7 100644 --- a/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h +++ b/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,11 +23,11 @@ #define MODMULTIFRAMEFG_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmdata/dcsequen.h" -#include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcdatset.h" -#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" /** Class managing the data from the Multi-Frame Functional Group Module. The @@ -38,255 +38,250 @@ class DCMTK_DCMIOD_EXPORT IODMultiFrameFGModule : public IODModule { public: - - // Forward declaration - class ConcatenationInfo; - - /** Constructor - * @param data The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODMultiFrameFGModule(OFshared_ptr data, - OFshared_ptr rules); - - /** Constructor - */ - IODMultiFrameFGModule(); - - /** Virtual destructor - */ - virtual ~IODMultiFrameFGModule(); - - /** Get name of the module ("MultiframeFunctionalGroupsModule") - * @return Name of the module ("MultiframeFunctionalGroupsModule") - */ - virtual OFString getName() const; - - /** Reset attribute rules to their default values - */ - virtual void resetRules(); - - // -- getters -- - - /** Get Instance Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getInstanceNumber(Sint32 &value, - const unsigned int pos = 0); - - /** Get Content Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getContentDate(OFString &value, - const signed long pos = 0); - - /** Get Content Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getContentTime(OFString &value, - const signed long pos = 0); - - /** Get Number of Frames - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getNumberOfFrames(Sint32 &value, - const unsigned int pos = 0); - - /** Get Representative Frame Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getRepresentativeFrameNumber(Uint16 &value, - const unsigned int pos = 0); - - /** Get Concatenation Information - * @return Reference to the concatenation information - */ - virtual ConcatenationInfo& getConcatenationInfo(); - - // -- setters -- - - /** Set Instance Number - * @param value Value to be stored - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setInstanceNumber(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Content Date - * @param value Value to be stored - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setContentDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Content Time - * @param value Value to be stored - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setContentTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Number of Frames - * @param value Value to be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setNumberOfFrames(const Uint32 value); - - /** Set Representative Frame Number - * @param value Value to be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRepresentativeFrameNumber(const Uint16 value); - - /** Set concatenation information - * @param concatenationInfo The concatenation info to set - * @return EC_Normal if successful, error otherwise - */ - virtual OFCondition setConcatenationInfo(const ConcatenationInfo& concatenationInfo); - - /** Helper class encapsulating concatenation information, including - * Concatenation Frame Offset Number, - * Concatenation UID, - * SOP Instance UID of Concatenation Source, - * In-concatenation Number, - * In-concatenation Total Number - */ - class DCMTK_DCMIOD_EXPORT ConcatenationInfo : public IODComponent - { - - public: + // Forward declaration + class ConcatenationInfo; /** Constructor * @param data The item to be used for data storage. If NULL, the * class creates an empty data container. - * @param rules The rule set where this classes rules are added to. If NULL, the - * class creates an empty rule set. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. */ - ConcatenationInfo(OFshared_ptr data, - OFshared_ptr rules); + IODMultiFrameFGModule(OFshared_ptr data, OFshared_ptr rules); /** Constructor - * @param parent The parent component of this class (if applicable, might be NULL) */ - ConcatenationInfo(IODComponent* parent = NULL); + IODMultiFrameFGModule(); /** Virtual destructor */ - virtual ~ConcatenationInfo(); + virtual ~IODMultiFrameFGModule(); + + /** Get name of the module ("MultiframeFunctionalGroupsModule") + * @return Name of the module ("MultiframeFunctionalGroupsModule") + */ + virtual OFString getName() const; - /** Resets attribute rules to their default values + /** Reset attribute rules to their default values */ virtual void resetRules(); - /** Get name of this component ("ConcatenationInfo") + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise */ - virtual OFString getName() const; + virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); // -- getters -- - /** Get Concatenation Frame Offset Number + /** Get Instance Number * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - OFCondition getConcatenationFrameOffsetNumber(Uint32& value, - const unsigned int pos); + virtual OFCondition getInstanceNumber(Sint32& value, const unsigned int pos = 0); - /** Get Concatenation UID + /** Get Content Date * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - OFCondition getConcatenationUID(OFString& value, - const signed long pos); + virtual OFCondition getContentDate(OFString& value, const signed long pos = 0); - /** Get SOP Instance UID of Concatenation Source + /** Get Content Time * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - OFCondition getSOPInstanceUIDOfConcatenationSource(OFString& value, - const signed long pos); + virtual OFCondition getContentTime(OFString& value, const signed long pos = 0); - /** Get Concatenation Number + /** Get Number of Frames * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - OFCondition getInConcatenationNumber(Uint16& value, - const unsigned int pos); + virtual OFCondition getNumberOfFrames(Sint32& value, const unsigned int pos = 0); - /** Get Concatenation Total Number + /** Get Representative Frame Number * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - OFCondition getInConcatenationTotalNumber(Uint16& value, - const unsigned int pos); + virtual OFCondition getRepresentativeFrameNumber(Uint16& value, const unsigned int pos = 0); + + /** Get Concatenation Information + * @return Reference to the concatenation information + */ + virtual ConcatenationInfo& getConcatenationInfo(); // -- setters -- - /** Set Concatenation Frame Offset Number + /** Set Instance Number * @param value Value to be stored + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setConcatenationFrameOffsetNumber(const Uint32 value); + virtual OFCondition setInstanceNumber(const OFString& value, const OFBool checkValue = OFTrue); - /** Set Concatenation UID + /** Set Content Date * @param value Value to be stored - * @param checkValue If OFTrue, the value is checked for conformance - * (VR = UID and VM = 1). + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setConcatenationUID(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setContentDate(const OFString& value, const OFBool checkValue = OFTrue); - /** Set SOP Instance UID of Concatenation Source + /** Set Content Time * @param value Value to be stored - * @param checkValue If OFTrue, the value is checked for conformance - * (VR = UID and VM = 1). + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSOPInstanceUIDOfConcatenationSource(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setContentTime(const OFString& value, const OFBool checkValue = OFTrue); - /** Set In-concatenation Number + /** Set Number of Frames * @param value Value to be stored * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setInConcatenationNumber(const Uint16 value); + virtual OFCondition setNumberOfFrames(const Uint32 value); - /** Set In-concatenation Total Number + /** Set Representative Frame Number * @param value Value to be stored * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setInConcatenationTotalNumber(const Uint16 value); - - }; // ConcatenationInfoClass + virtual OFCondition setRepresentativeFrameNumber(const Uint16 value); + /** Set concatenation information + * @param concatenationInfo The concatenation info to set + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition setConcatenationInfo(const ConcatenationInfo& concatenationInfo); + + /** Helper class encapsulating concatenation information, including + * Concatenation Frame Offset Number, + * Concatenation UID, + * SOP Instance UID of Concatenation Source, + * In-concatenation Number, + * In-concatenation Total Number + */ + class DCMTK_DCMIOD_EXPORT ConcatenationInfo : public IODComponent + { + + public: + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + ConcatenationInfo(OFshared_ptr data, OFshared_ptr rules); + + /** Constructor + * @param parent The parent component of this class (if applicable, might be NULL) + */ + ConcatenationInfo(IODComponent* parent = NULL); + + /** Virtual destructor + */ + virtual ~ConcatenationInfo(); + + /** Resets attribute rules to their default values + */ + virtual void resetRules(); + + /** Get name of this component ("ConcatenationInfo") + * @return Name of this component + */ + virtual OFString getName() const; + + // -- getters -- + + /** Get Concatenation Frame Offset Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getConcatenationFrameOffsetNumber(Uint32& value, const unsigned int pos = 0); + + /** Get Concatenation UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getConcatenationUID(OFString& value, const signed long pos = -1); + + /** Get SOP Instance UID of Concatenation Source + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getSOPInstanceUIDOfConcatenationSource(OFString& value, const signed long pos = -1); + + /** Get Concatenation Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getInConcatenationNumber(Uint16& value, const unsigned int pos = 0); + + /** Get Concatenation Total Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getInConcatenationTotalNumber(Uint16& value, const unsigned int pos = 0); + + // -- setters -- + + /** Set Concatenation Frame Offset Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setConcatenationFrameOffsetNumber(const Uint32 value); + + /** Set Concatenation UID + * @param value Value to be stored + * @param checkValue If OFTrue, the value is checked for conformance + * (VR = UID and VM = 1). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setConcatenationUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set SOP Instance UID of Concatenation Source + * @param value Value to be stored + * @param checkValue If OFTrue, the value is checked for conformance + * (VR = UID and VM = 1). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPInstanceUIDOfConcatenationSource(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set In-concatenation Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInConcatenationNumber(const Uint16 value); + + /** Set In-concatenation Total Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInConcatenationTotalNumber(const Uint16 value); + + }; // ConcatenationInfoClass private: + /// Concatenation Information + ConcatenationInfo m_ConcatenationInfo; - /// Concatenation Information - ConcatenationInfo m_ConcatenationInfo; - - /// Module name ("MultiframeFunctionalGroupsModule" - static const OFString m_ModuleName; + /// Module name ("MultiframeFunctionalGroupsModule" + static const OFString m_ModuleName; }; #endif // MODMULTIFRAMEFG_H diff --git a/dcmiod/include/dcmtk/dcmiod/modpatient.h b/dcmiod/include/dcmtk/dcmiod/modpatient.h index 3e9422cc..af4dbf89 100644 --- a/dcmiod/include/dcmtk/dcmiod/modpatient.h +++ b/dcmiod/include/dcmtk/dcmiod/modpatient.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,119 +23,107 @@ #define MODPATIENT_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofvector.h" #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the Patient Module: - * - * Patient's Name: (PN, 1, 2) - * Patient ID: (LO, 1, 2) - * Patient's Birth Date: (DA, 1, 2) - * Patient's Sex: (CS, 1, 2) - */ + * + * Patient's Name: (PN, 1, 2) + * Patient ID: (LO, 1, 2) + * Patient's Birth Date: (DA, 1, 2) + * Patient's Sex: (CS, 1, 2) + */ class DCMTK_DCMIOD_EXPORT IODPatientModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODPatientModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODPatientModule(); - - /** Destructor - */ - virtual ~IODPatientModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("PatientModule") - * @return Name of the module ("PatientModule") - */ - virtual OFString getName() const; - - /** Get Patient's Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientName(OFString &value, - const signed long pos = 0) const; - - /** Get Patient ID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientID(OFString &value, - const signed long pos = 0) const; - - /** Get Patient's Birth Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientBirthDate(OFString &value, - const signed long pos = 0) const; - - /** Get Patient's Sex - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientSex(OFString &value, - const signed long pos = 0) const; - - - /** Set Patient's Name - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientName(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient ID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient's Birth Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientBirthDate(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient's Sex - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientSex(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODPatientModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODPatientModule(); + + /** Destructor + */ + virtual ~IODPatientModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("PatientModule") + * @return Name of the module ("PatientModule") + */ + virtual OFString getName() const; + + /** Get Patient's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientName(OFString& value, const signed long pos = 0) const; + + /** Get Patient ID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientID(OFString& value, const signed long pos = 0) const; + + /** Get Patient's Birth Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientBirthDate(OFString& value, const signed long pos = 0) const; + + /** Get Patient's Sex + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientSex(OFString& value, const signed long pos = 0) const; + + /** Set Patient's Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientName(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient ID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient's Birth Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientBirthDate(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient's Sex + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientSex(const OFString& value, const OFBool checkValue = OFTrue); private: - - /// The name of this module ("PatientModule") - static const OFString m_ModuleName; + /// The name of this module ("PatientModule") + static const OFString m_ModuleName; }; #endif // MODPATIENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h b/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h index 11181e26..1f0ddf4e 100644 --- a/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h +++ b/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,123 +23,112 @@ #define MODPATIENTSTUDY_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofoption.h" -#include "dcmtk/ofstd/ofvector.h" #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmiod/iodrules.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the Patient Study Module: - * - * Admitting Diagnoses Description: (LO, 1-n, 3) - * Patient's Age: (AS, 1, 3) - * Patient's Size: (DS, 1, 3) - * Patient's Weight: (DS,1, 3) - */ + * + * Admitting Diagnoses Description: (LO, 1-n, 3) + * Patient's Age: (AS, 1, 3) + * Patient's Size: (DS, 1, 3) + * Patient's Weight: (DS,1, 3) + */ class DCMTK_DCMIOD_EXPORT IODPatientStudyModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODPatientStudyModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODPatientStudyModule(); - - /** Destructor - */ - virtual ~IODPatientStudyModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module ("PatientStudyModule") - * @return Name of the module ("PatientStudyModule") - */ - virtual OFString getName() const; - - /** Get Admitting Diagnoses Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getAdmittingDiagnosesDescription(OFString& value, - const signed long pos = 0) const; - - /** Get Patient's Age (string as defined by VR "AS", see DICOM part 5) - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientAge(OFString &value, - const signed long pos = 0) const; - - /** Get Patient's Weight (in kilograms) - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientWeight(Float64 &value, - const unsigned long pos = 0) const; - - /** Get Patient's Size (in meters) - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientSize(Float64 &value, - const unsigned long pos = 0) const; - - /** Set Admitting Diagnoses Description - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setAdmittingDiagnosesDescription(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient's Age (formatted as defined by VR "AS", see part 5 of the standard) - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (AS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientAge(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient's Size (in meters) - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientSize(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Patient's Weight (in kilograms) - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientWeight(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODPatientStudyModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODPatientStudyModule(); + + /** Destructor + */ + virtual ~IODPatientStudyModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("PatientStudyModule") + * @return Name of the module ("PatientStudyModule") + */ + virtual OFString getName() const; + + /** Get Admitting Diagnoses Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAdmittingDiagnosesDescription(OFString& value, const signed long pos = 0) const; + + /** Get Patient's Age (string as defined by VR "AS", see DICOM part 5) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientAge(OFString& value, const signed long pos = 0) const; + + /** Get Patient's Weight (in kilograms) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientWeight(Float64& value, const unsigned long pos = 0) const; + + /** Get Patient's Size (in meters) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientSize(Float64& value, const unsigned long pos = 0) const; + + /** Set Admitting Diagnoses Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAdmittingDiagnosesDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient's Age (formatted as defined by VR "AS", see part 5 of the standard) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (AS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientAge(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient's Size (in meters) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientSize(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Patient's Weight (in kilograms) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientWeight(const OFString& value, const OFBool checkValue = OFTrue); private: - - /// The name of this module ("PatientStudyModule") - static const OFString m_ModuleName; + /// The name of this module ("PatientStudyModule") + static const OFString m_ModuleName; }; #endif // MODPATIENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h b/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h index 901825d2..5b263e3c 100644 --- a/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h +++ b/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,10 +23,10 @@ #define MODSEGMENTATIONSERIES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofmem.h" -#include "dcmtk/ofstd/ofvector.h" #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" /** Class representing the Segmentation Series Module: * @@ -40,102 +40,91 @@ class DCMTK_DCMIOD_EXPORT IODSegmentationSeriesModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODSegmentationSeriesModule(OFshared_ptr item, - OFshared_ptr rules); - /** Constructor - */ - IODSegmentationSeriesModule(); - - /** Destructor - */ - virtual ~IODSegmentationSeriesModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of this module - * @return Name of the module ("SegmentationSeriesModule") - */ - virtual OFString getName() const; - - /** Get Modality (always returns "SEG") - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getModality(OFString &value, - const signed long pos = 0) const; - - /** Get Series Number - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSeriesNumber(OFString &value, - const signed long pos = 0) const; - - /** Get Referenced PPS SOP Class UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPPSSOPClassUID(OFString &value, - const signed long pos = 0) const; - - /** Get Referenced PPS SOP Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPPSSOPInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Set Series Number - * @param value Value to be set (single value only). If an empty string is passed, - * the value "1" is set when displaying or writing the document since - * the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSeriesNumber(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Referenced PPS SOP Class UID - * @param value Value to be set (single value only). If an empty string is passed, - * the value "1" is set when displaying or writing the document since - * the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPPSSOPClassUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Referenced PPS SOP Instance UID - * @param value Value to be set (single value only). If an empty string is passed, - * the value "1" is set when displaying or writing the document since - * the corresponding DICOM attribute is mandatory. - * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPPSSOPInstanceUID(const OFString &value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODSegmentationSeriesModule(OFshared_ptr item, OFshared_ptr rules); + /** Constructor + */ + IODSegmentationSeriesModule(); + + /** Destructor + */ + virtual ~IODSegmentationSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of this module + * @return Name of the module ("SegmentationSeriesModule") + */ + virtual OFString getName() const; + + /** Get Modality (always returns "SEG") + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString& value, const signed long pos = 0) const; + + /** Get Series Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesNumber(OFString& value, const signed long pos = 0) const; + + /** Get Referenced PPS SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPPSSOPClassUID(OFString& value, const signed long pos = 0) const; + + /** Get Referenced PPS SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPPSSOPInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Set Series Number + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesNumber(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Referenced PPS SOP Class UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPPSSOPClassUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Referenced PPS SOP Instance UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPPSSOPInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); private: - - /// Name of this module ("SegmentationSeriesModule") - static const OFString m_ModuleName; - + /// Name of this module ("SegmentationSeriesModule") + static const OFString m_ModuleName; }; #endif // MODSEGMENTATIONSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsopcommon.h b/dcmiod/include/dcmtk/dcmiod/modsopcommon.h index ef99908c..fab033e3 100644 --- a/dcmiod/include/dcmtk/dcmiod/modsopcommon.h +++ b/dcmiod/include/dcmtk/dcmiod/modsopcommon.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,189 +23,171 @@ #define MODSOPCOMMON_H #include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" #include "dcmtk/ofstd/ofcond.h" #include "dcmtk/ofstd/ofstring.h" -#include "dcmtk/dcmiod/modbase.h" - /** Class representing the SOP Common Module. Supported Attributes: - * - * SOP Class UID: (UI, 1, 1) - * SOP Instance UID: (UI, 1, 1) - * Specific Character Set: (CS, 1-n, 1C) - * Instance Creation Date: (DA, 1, 3) - * Instance Creation Time: (TM, 1, 3) - * Instance Creator UID: (UI, 1, 3) - * Timezone Offset from UTC: (SH, 1, 3) - * - */ + * + * SOP Class UID: (UI, 1, 1) + * SOP Instance UID: (UI, 1, 1) + * Specific Character Set: (CS, 1-n, 1C) + * Instance Creation Date: (DA, 1, 3) + * Instance Creation Time: (TM, 1, 3) + * Instance Creator UID: (UI, 1, 3) + * Timezone Offset from UTC: (SH, 1, 3) + * + */ class DCMTK_DCMIOD_EXPORT IODSOPCommonModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODSOPCommonModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODSOPCommonModule(); - - /** Destructor - */ - virtual ~IODSOPCommonModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Set missing values by inventing "default values". Automatically - * called during write() by IODComponent. - */ - virtual void inventMissing(); - - /** Get name of module - * @return Name of the module ("SOPCommonModule") - */ - virtual OFString getName() const; - - /** Make sure that the module contains a SOP Instance UID, i.e.\ a new one - * is created if empty. An invalid UID is corrected if desired. - * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing - */ - virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); - - /** Get SOP Class UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSOPClassUID(OFString &value, - const signed long pos = 0) const; - - /** Get SOP Instance UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSOPInstanceUID(OFString &value, - const signed long pos = 0) const; - - /** Get Instance Creator UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getInstanceCreatorUID(OFString &value, - const signed long pos = 0) const; - - /** Get Timeho e Offset from UTC - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTimezoneOffsetFromUTC(OFString &value, - const signed long pos = 0) const; - - /** Get Specific Character Set - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSpecificCharacterSet(OFString &value, - const signed long pos = 0) const; - - /** Get Instance Creation Date - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getInstanceCreationDate(OFString &value, - const signed long pos = 0) const; - - /** Get Instance Creation Time - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getInstanceCreationTime(OFString &value, - const signed long pos = 0) const; - - /** Set SOP Instance UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSOPInstanceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set SOP Class UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and - * VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSOPClassUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Specific Character Set. The internal enumerated value is set accordingly. - * Please note that code extensions techniques are not supported. Therefore, only - * a single value can be passed. - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSpecificCharacterSet(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Instance Creation Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setInstanceCreationDate(const OFString &value, - const OFBool checkValue = OFTrue); - /** Set Instance Creation Date - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setInstanceCreationTime(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Instance Creator UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UID) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setInstanceCreatorUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Timezone Offset From UTC - * @param value Value to be set (single value only) or "" for no value. - * Encoded as an ASCII string in the format “&ZZXX”. The components of this - * string, from left to right, are & = “+” or “-”, and ZZ = Hours and - * XX = Minutes of offset. - * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ virtual OFCondition setTimeZoneOffsetFromUTC(const OFString &value, - const OFBool checkValue = OFTrue) const; + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODSOPCommonModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODSOPCommonModule(); + + /** Destructor + */ + virtual ~IODSOPCommonModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Get name of module + * @return Name of the module ("SOPCommonModule") + */ + virtual OFString getName() const; + + /** Make sure that the module contains a SOP Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Get SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSOPClassUID(OFString& value, const signed long pos = 0) const; + + /** Get SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSOPInstanceUID(OFString& value, const signed long pos = 0) const; + + /** Get Instance Creator UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreatorUID(OFString& value, const signed long pos = 0) const; + + /** Get Timeho e Offset from UTC + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTimezoneOffsetFromUTC(OFString& value, const signed long pos = 0) const; + + /** Get Specific Character Set + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSpecificCharacterSet(OFString& value, const signed long pos = 0) const; + + /** Get Instance Creation Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreationDate(OFString& value, const signed long pos = 0) const; + + /** Get Instance Creation Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreationTime(OFString& value, const signed long pos = 0) const; + + /** Set SOP Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPInstanceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set SOP Class UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and + * VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPClassUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Specific Character Set. The internal enumerated value is set accordingly. + * Please note that code extensions techniques are not supported. Therefore, only + * a single value can be passed. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSpecificCharacterSet(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Instance Creation Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreationDate(const OFString& value, const OFBool checkValue = OFTrue); + /** Set Instance Creation Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreationTime(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Instance Creator UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UID) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreatorUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Timezone Offset From UTC + * @param value Value to be set (single value only) or "" for no value. + * Encoded as an ASCII string in the format “&ZZXX”. The components of this + * string, from left to right, are & = “+” or “-”, and ZZ = Hours and + * XX = Minutes of offset. + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTimeZoneOffsetFromUTC(const OFString& value, const OFBool checkValue = OFTrue) const; private: - - /// Name of this module ("SOPCommonModule") - static const OFString m_ModuleName; - + /// Name of this module ("SOPCommonModule") + static const OFString m_ModuleName; }; #endif // MODSOPCOMMON_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h b/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h index 7a46b007..cef7ea83 100644 --- a/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h +++ b/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,8 @@ #define MODSYNCHRONIZATION_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofoption.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofoption.h" /** Class representing the Synchronization Module: * @@ -41,15 +41,13 @@ class DCMTK_DCMIOD_EXPORT IODSynchronizationModule : public IODModule { public: - /** Constructor * @param item The item to be used for data storage. If NULL, the * class creates an empty data container. * @param rules The rule set for this class. If NULL, the class creates * one from scratch and adds its values. */ - IODSynchronizationModule(OFshared_ptr item, - OFshared_ptr rules); + IODSynchronizationModule(OFshared_ptr item, OFshared_ptr rules); /** Constructor */ @@ -69,32 +67,29 @@ public: virtual OFString getName() const; /** Get Synchronization Frame of Reference UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getSynchronizationFrameOfReferenceUID(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getSynchronizationFrameOfReferenceUID(OFString& value, const signed long pos = 0) const; /** Get Synchronization Trigger - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getSynchronizationTrigger(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getSynchronizationTrigger(OFString& value, const signed long pos = 0) const; /** Get Trigger Source or Type - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getTriggerSourceOrType(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getTriggerSourceOrType(OFString& value, const signed long pos = 0) const; /** Get Synchronization Channel - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise */ virtual OFCondition getSynchronizationChannel(OFVector& value) const; @@ -103,32 +98,28 @@ public: * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getAcquisitionTimeSynchronized(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getAcquisitionTimeSynchronized(OFString& value, const signed long pos = 0) const; /** Get Time Source * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getTimeSource(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getTimeSource(OFString& value, const signed long pos = 0) const; /** Get Time Distribution Protocol * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getTimeDistributionProtocol(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getTimeDistributionProtocol(OFString& value, const signed long pos = 0) const; /** Get NTP Source Address * @param value Reference to variable in which the value should be stored * @param pos Index of the value to get (0..vm-1), -1 for all components * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition getNTPSourceAddress(OFString& value, - const signed long pos = 0) const; + virtual OFCondition getNTPSourceAddress(OFString& value, const signed long pos = 0) const; /** Set Synchronization Frame of Reference UID * @param value Value to be set @@ -136,8 +127,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSynchronizationFrameofReferenceUID(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setSynchronizationFrameofReferenceUID(const OFString& value, const OFBool checkValue = OFTrue); /** Set Synchronization Trigger * @param value Value to be set @@ -145,8 +135,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSynchronizationTrigger(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setSynchronizationTrigger(const OFString& value, const OFBool checkValue = OFTrue); /** Set Trigger Source or Type * @param value Value to be set @@ -154,8 +143,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setTriggerSourceOrType(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setTriggerSourceOrType(const OFString& value, const OFBool checkValue = OFTrue); /** Set Synchronization Channel * @param value Value to be set @@ -163,7 +151,7 @@ public: * with other setter functions). * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setSynchronizationChannel(const OFPair &value, + virtual OFCondition setSynchronizationChannel(const OFPair& value, const OFBool checkValue = OFTrue); /** Set Acquisition Time Synchronized @@ -172,8 +160,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setAcquisitionTimeSynchronized(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setAcquisitionTimeSynchronized(const OFString& value, const OFBool checkValue = OFTrue); /** Set Time Source * @param value Value to be set @@ -181,8 +168,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setTimeSource(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setTimeSource(const OFString& value, const OFBool checkValue = OFTrue); /** Set Time Distribution Protocol * @param value Value to be set @@ -190,8 +176,7 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setTimeDistributionProtocol(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setTimeDistributionProtocol(const OFString& value, const OFBool checkValue = OFTrue); /** Set NTP Source Address * @param value Value to be set @@ -199,37 +184,33 @@ public: * if enabled * @return EC_Normal if successful, an error code otherwise */ - virtual OFCondition setNTPSourceAddress(const OFString &value, - const OFBool checkValue = OFTrue); + virtual OFCondition setNTPSourceAddress(const OFString& value, const OFBool checkValue = OFTrue); protected: + /** Check whether given string is a valid value for attribute + * Acquisition Time Synchronized + * @param value The value to check + * @return OFTrue if value is valid for this attribute, OFFalse otherwise + */ + virtual OFBool isValidAcquisitionTimeSynchronized(const OFString& value); - /** Check whether given string is a valid value for attribute - * Acquisition Time Synchronized - * @param value The value to check - * @return OFTrue if value is valid for this attribute, OFFalse otherwise - */ - virtual OFBool isValidAcquisitionTimeSynchronized(const OFString& value); - - /** Check whether given string is a valid value for attribute - * Time Distribution Protocol - * @param value The value to check - * @return OFTrue if value is valid for this attribute, OFFalse otherwise - */ - virtual OFBool isValidTimeDistributionProtocol(const OFString& value); - - /** Check whether given string is a valid value for attribute - * Synchronization Trigger - * @param value The value to check - * @return OFTrue if value is valid for this attribute, OFFalse otherwise - */ - virtual OFBool isValidSynchronizationTrigger(const OFString& value); + /** Check whether given string is a valid value for attribute + * Time Distribution Protocol + * @param value The value to check + * @return OFTrue if value is valid for this attribute, OFFalse otherwise + */ + virtual OFBool isValidTimeDistributionProtocol(const OFString& value); -private: + /** Check whether given string is a valid value for attribute + * Synchronization Trigger + * @param value The value to check + * @return OFTrue if value is valid for this attribute, OFFalse otherwise + */ + virtual OFBool isValidSynchronizationTrigger(const OFString& value); +private: /// Module name "SynchronizationModule" static const OFString m_ModuleName; - }; #endif // MODSYNCHRONIZATION_H diff --git a/dcmiod/include/dcmtk/dcmiod/modusfor.h b/dcmiod/include/dcmtk/dcmiod/modusfor.h index 5cde7646..ef2d55f7 100644 --- a/dcmiod/include/dcmtk/dcmiod/modusfor.h +++ b/dcmiod/include/dcmtk/dcmiod/modusfor.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,8 +23,8 @@ #define MODUSFOR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofoption.h" #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/ofstd/ofoption.h" /** Class representing the Frame of Reference Module: * @@ -42,188 +42,170 @@ class DCMTK_DCMIOD_EXPORT IODUSFoRModule : public IODModule { public: - - /** Constructor - * @param item The item to be used for data storage. If NULL, the - * class creates an empty data container. - * @param rules The rule set for this class. If NULL, the class creates - * one from scratch and adds its values. - */ - IODUSFoRModule(OFshared_ptr item, - OFshared_ptr rules); - - /** Constructor - */ - IODUSFoRModule(); - - /** Destructor - */ - virtual ~IODUSFoRModule(); - - /** Resets rules to their original values - */ - virtual void resetRules(); - - /** Get name of module - * @return Name of the module ("UltrasoundFrameOfReferenceModule") - */ - virtual OFString getName() const; - - /** Get Volume Frame of Reference UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumeFrameOfReferenceUID(OFString& value, - const signed long pos = 0) const; - - /** Get Position Reference Indicator - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getUltrasoundAcquisitionGeometry(OFString& value, - const signed long pos = 0) const; - - /** Get Apex Position - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getApexPosition(Float64& value, - const unsigned long pos = 0) const; - - /** Get Apex Position - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getApexPosition(OFVector& value); - - /** Get Volume to Transducer Relationship - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetoTransducerRelationship(OFString& value, - const signed long pos = 0); - - /** Get Volume to Table Mapping Matrix - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetoTransducerMappingMatrix(Float64& value, - const signed long pos = 0) const; - - /** Get Volume to Table Mapping Matrix - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetoTransducerMappingMatrix(OFVector& value); - - /** Get Patient Frame of Reference Source - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getPatientFrameofReferenceSource(OFString& value, - const signed long pos = 0); - - /** Get Table Frame of Reference UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTableFrameofReferenceUID(OFString& value, - const signed long pos = 0); - - /** Get Volume to Table Mapping Matrix - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetoTableMappingMatrix(Float64& value, - const signed long pos = 0) const; - - /** Get Volume to Table Mapping Matrix - * @param value Reference to variable in which the value should be stored - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getVolumetoTableMappingMatrix(OFVector& value); - - /** Set Volume Frame Of Reference UID - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVolumeFrameOfReferenceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Ultrasound Acquisition Geometry - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setUltrasoundAcquisitionGeometry(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Apex Position - * @param xValue xValue to be set - * @param yValue yValue to be set - * @param zValue zValue to be set - * @param checkValue Does nothing at the moment - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setApexPosition(const Float64& xValue, - const Float64& yValue, - const Float64& zValue, - const OFBool checkValue = OFTrue); - - /** Set Volume to Transducer Relationship - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVolumetoTransducerRelationship(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Volume to Transducer Mapping Matrix - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVolumetoTransducerMappingMatrix(const OFVector& value, - const OFBool checkValue = OFTrue); - - /** Set Patient Frame of Reference Source - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setPatientFrameOfReferenceSource(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Table Frame of Reference UID - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setTableFrameofReferenceUID(const OFString &value, - const OFBool checkValue = OFTrue); - - /** Set Volume to Table Mapping Matrix - * @param value Value to be set - * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setVolumeToTableMappingMatrix(const OFVector& value, - const OFBool checkValue = OFTrue); + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODUSFoRModule(OFshared_ptr item, OFshared_ptr rules); + + /** Constructor + */ + IODUSFoRModule(); + + /** Destructor + */ + virtual ~IODUSFoRModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("UltrasoundFrameOfReferenceModule") + */ + virtual OFString getName() const; + + /** Get Volume Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumeFrameOfReferenceUID(OFString& value, const signed long pos = 0) const; + + /** Get Position Reference Indicator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUltrasoundAcquisitionGeometry(OFString& value, const signed long pos = 0) const; + + /** Get Apex Position + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getApexPosition(Float64& value, const unsigned long pos = 0) const; + + /** Get Apex Position + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getApexPosition(OFVector& value); + + /** Get Volume to Transducer Relationship + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerRelationship(OFString& value, const signed long pos = 0); + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerMappingMatrix(Float64& value, const unsigned long pos = 0) const; + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerMappingMatrix(OFVector& value); + + /** Get Patient Frame of Reference Source + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientFrameofReferenceSource(OFString& value, const signed long pos = 0); + + /** Get Table Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTableFrameofReferenceUID(OFString& value, const signed long pos = 0); + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTableMappingMatrix(Float64& value, const unsigned long pos = 0) const; + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTableMappingMatrix(OFVector& value); + + /** Set Volume Frame Of Reference UID + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeFrameOfReferenceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Ultrasound Acquisition Geometry + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setUltrasoundAcquisitionGeometry(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Apex Position + * @param xValue xValue to be set + * @param yValue yValue to be set + * @param zValue zValue to be set + * @param checkValue Does nothing at the moment + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setApexPosition(const Float64& xValue, + const Float64& yValue, + const Float64& zValue, + const OFBool checkValue = OFTrue); + + /** Set Volume to Transducer Relationship + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumetoTransducerRelationship(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Volume to Transducer Mapping Matrix + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumetoTransducerMappingMatrix(const OFVector& value, + const OFBool checkValue = OFTrue); + + /** Set Patient Frame of Reference Source + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientFrameOfReferenceSource(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Table Frame of Reference UID + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTableFrameofReferenceUID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Volume to Table Mapping Matrix + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeToTableMappingMatrix(const OFVector& value, const OFBool checkValue = OFTrue); private: - - /// Module name "UltrasoundFrameOfReferenceModule" - static const OFString m_ModuleName; - + /// Module name "UltrasoundFrameOfReferenceModule" + static const OFString m_ModuleName; }; #endif // MODUSFOR_H diff --git a/dcmiod/libsrc/Makefile.dep b/dcmiod/libsrc/Makefile.dep index a7cbbde6..954c7d0e 100644 --- a/dcmiod/libsrc/Makefile.dep +++ b/dcmiod/libsrc/Makefile.dep @@ -1,28 +1,23 @@ -cielabutil.o: cielabutil.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/cielabutil.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ +cielabutil.o: cielabutil.cc ../include/dcmtk/dcmiod/cielabutil.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h -iodcommn.o: iodcommn.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/iodcommn.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h +iodcommn.o: iodcommn.cc ../include/dcmtk/dcmiod/iodcommn.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -35,6 +30,9 @@ iodcommn.o: iodcommn.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -45,8 +43,10 @@ iodcommn.o: iodcommn.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmiod/modcommoninstanceref.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ @@ -123,24 +123,22 @@ iodcommn.o: iodcommn.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodmacro.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodreferences.h \ + ../include/dcmtk/dcmiod/modequipment.h ../include/dcmtk/dcmiod/modfor.h \ + ../include/dcmtk/dcmiod/modgeneralseries.h \ + ../include/dcmtk/dcmiod/modgeneralstudy.h \ + ../include/dcmtk/dcmiod/modpatient.h \ ../include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../include/dcmtk/dcmiod/modgeneralstudy.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../include/dcmtk/dcmiod/modequipment.h \ - ../include/dcmtk/dcmiod/modgeneralseries.h \ - ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modsopcommon.h \ - ../include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../include/dcmtk/dcmiod/iodreferences.h \ - ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/modsopcommon.h ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h iodcontentitemmacro.o: iodcontentitemmacro.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ @@ -186,41 +184,37 @@ iodcontentitemmacro.o: iodcontentitemmacro.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmiod/iodcontentitemmacro.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodcontentitemmacro.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -256,26 +250,30 @@ iodcontentitemmacro.o: iodcontentitemmacro.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ - ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h -iodmacro.o: iodmacro.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +iodmacro.o: iodmacro.cc ../include/dcmtk/dcmiod/iodmacro.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ @@ -373,33 +371,43 @@ iodmacro.o: iodmacro.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -iodreferences.o: iodreferences.cc \ +iodreferences.o: iodreferences.cc ../include/dcmtk/dcmiod/iodreferences.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ - ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ + ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -411,62 +419,44 @@ iodreferences.o: iodreferences.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodreferences.h \ - ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h -iodrules.o: iodrules.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h +iodrules.o: iodrules.cc ../include/dcmtk/dcmiod/iodrules.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -479,6 +469,9 @@ iodrules.o: iodrules.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -489,34 +482,37 @@ iodrules.o: iodrules.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h -iodtypes.o: iodtypes.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ - ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +iodtypes.o: iodtypes.cc ../include/dcmtk/dcmiod/iodtypes.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ @@ -543,32 +539,41 @@ iodtypes.o: iodtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h -iodutil.o: iodutil.cc ../../config/include/dcmtk/config/osconfig.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ - ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ +iodutil.o: iodutil.cc ../include/dcmtk/dcmiod/iodutil.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -581,48 +586,38 @@ iodutil.o: iodutil.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h modacquisitioncontext.o: modacquisitioncontext.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modacquisitioncontext.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ @@ -737,27 +732,23 @@ modacquisitioncontext.o: modacquisitioncontext.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -modbase.o: modbase.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ +modbase.o: modbase.cc ../include/dcmtk/dcmiod/modbase.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -769,10 +760,14 @@ modbase.o: modbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -796,43 +791,43 @@ modbase.o: modbase.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h + ../../ofstd/include/dcmtk/ofstd/oftime.h modcommoninstanceref.o: modcommoninstanceref.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -922,31 +917,25 @@ modcommoninstanceref.o: modcommoninstanceref.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodmacro.h \ + ../include/dcmtk/dcmiod/iodmacro.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmiod/iodreferences.h \ ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h modenhequipment.o: modenhequipment.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modenhequipment.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../include/dcmtk/dcmiod/iodtypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ @@ -961,6 +950,9 @@ modenhequipment.o: modenhequipment.cc \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -971,7 +963,10 @@ modenhequipment.o: modenhequipment.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ @@ -994,49 +989,41 @@ modenhequipment.o: modenhequipment.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h -modenhusimage.o: modenhusimage.cc \ +modenhusimage.o: modenhusimage.cc ../include/dcmtk/dcmiod/modenhusimage.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modenhusimage.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1048,36 +1035,40 @@ modenhusimage.o: modenhusimage.cc \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1122,42 +1113,38 @@ modenhusimage.o: modenhusimage.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h modenhusseries.o: modenhusseries.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modenhusseries.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ - ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1168,12 +1155,10 @@ modenhusseries.o: modenhusseries.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ @@ -1181,11 +1166,13 @@ modenhusseries.o: modenhusseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ @@ -1202,6 +1189,7 @@ modenhusseries.o: modenhusseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1246,26 +1234,24 @@ modenhusseries.o: modenhusseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -modequipment.o: modequipment.cc \ +modequipment.o: modequipment.cc ../include/dcmtk/dcmiod/modequipment.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modequipment.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../include/dcmtk/dcmiod/iodtypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ @@ -1280,6 +1266,9 @@ modequipment.o: modequipment.cc \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1290,7 +1279,10 @@ modequipment.o: modequipment.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ @@ -1313,35 +1305,34 @@ modequipment.o: modequipment.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h modfloatingpointimagepixel.o: modfloatingpointimagepixel.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modfloatingpointimagepixel.h \ - ../include/dcmtk/dcmiod/modimagepixelbase.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/modimagepixelbase.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -1353,10 +1344,14 @@ modfloatingpointimagepixel.o: modfloatingpointimagepixel.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1367,7 +1362,6 @@ modfloatingpointimagepixel.o: modfloatingpointimagepixel.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -1375,41 +1369,36 @@ modfloatingpointimagepixel.o: modfloatingpointimagepixel.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h -modfor.o: modfor.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ +modfor.o: modfor.cc ../include/dcmtk/dcmiod/modfor.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -1421,11 +1410,15 @@ modfor.o: modfor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ - ../../oflog/include/dcmtk/oflog/layout.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ @@ -1448,40 +1441,34 @@ modfor.o: modfor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h modgeneralimage.o: modgeneralimage.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modgeneralimage.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -1494,6 +1481,9 @@ modgeneralimage.o: modgeneralimage.cc \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1504,7 +1494,9 @@ modgeneralimage.o: modgeneralimage.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ @@ -1524,48 +1516,34 @@ modgeneralimage.o: modgeneralimage.cc \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ - ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h modgeneralseries.o: modgeneralseries.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modgeneralseries.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -1573,10 +1551,18 @@ modgeneralseries.o: modgeneralseries.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1588,36 +1574,40 @@ modgeneralseries.o: modgeneralseries.cc \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1662,43 +1652,37 @@ modgeneralseries.o: modgeneralseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h modgeneralstudy.o: modgeneralstudy.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modgeneralstudy.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1710,36 +1694,40 @@ modgeneralstudy.o: modgeneralstudy.cc \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -1784,10 +1772,12 @@ modgeneralstudy.o: modgeneralstudy.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -modhelp.o: modhelp.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modhelp.h \ +modhelp.o: modhelp.cc ../include/dcmtk/dcmiod/modhelp.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ @@ -1795,9 +1785,12 @@ modhelp.o: modhelp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/dcmiod/ioddef.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ @@ -1830,7 +1823,6 @@ modhelp.o: modhelp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -1838,32 +1830,28 @@ modhelp.o: modhelp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h -modimagepixel.o: modimagepixel.cc \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +modimagepixel.o: modimagepixel.cc ../include/dcmtk/dcmiod/modimagepixel.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modimagepixel.h \ - ../include/dcmtk/dcmiod/modimagepixelbase.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/modimagepixelbase.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -1875,10 +1863,14 @@ modimagepixel.o: modimagepixel.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1889,7 +1881,6 @@ modimagepixel.o: modimagepixel.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ @@ -1897,45 +1888,39 @@ modimagepixel.o: modimagepixel.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h modimagepixelbase.o: modimagepixelbase.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -1947,10 +1932,14 @@ modimagepixelbase.o: modimagepixelbase.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -1974,40 +1963,34 @@ modimagepixelbase.o: modimagepixelbase.cc \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h modmultiframedimension.o: modmultiframedimension.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -2020,6 +2003,9 @@ modmultiframedimension.o: modmultiframedimension.cc \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2030,7 +2016,9 @@ modmultiframedimension.o: modmultiframedimension.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ @@ -2050,24 +2038,25 @@ modmultiframedimension.o: modmultiframedimension.cc \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpath.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpath.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h modmultiframefg.o: modmultiframefg.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modmultiframefg.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ @@ -2083,13 +2072,6 @@ modmultiframefg.o: modmultiframefg.cc \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -2115,54 +2097,60 @@ modmultiframefg.o: modmultiframefg.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ - ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/modbase.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -modpatient.o: modpatient.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modpatient.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ +modpatient.o: modpatient.cc ../include/dcmtk/dcmiod/modpatient.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2253,38 +2241,36 @@ modpatient.o: modpatient.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h modpatientstudy.o: modpatientstudy.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modpatientstudy.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2375,36 +2361,38 @@ modpatientstudy.o: modpatientstudy.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h modsegmentationseries.o: modsegmentationseries.cc \ - ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmiod/modsegmentationseries.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ - ../../ofstd/include/dcmtk/ofstd/ofcast.h \ - ../../ofstd/include/dcmtk/ofstd/ofexport.h \ - ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2496,12 +2484,13 @@ modsegmentationseries.o: modsegmentationseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/ioddef.h \ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ - ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/iodutil.h \ + ../include/dcmtk/dcmiod/iodutil.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h -modsopcommon.o: modsopcommon.cc \ +modsopcommon.o: modsopcommon.cc ../include/dcmtk/dcmiod/modsopcommon.h \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modsopcommon.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ @@ -2509,16 +2498,10 @@ modsopcommon.o: modsopcommon.cc \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ @@ -2529,10 +2512,14 @@ modsopcommon.o: modsopcommon.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2556,50 +2543,38 @@ modsopcommon.o: modsopcommon.cc \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h modsynchronization.o: modsynchronization.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modsynchronisation.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -2607,10 +2582,15 @@ modsynchronization.o: modsynchronization.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2621,56 +2601,57 @@ modsynchronization.o: modsynchronization.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h -modusfor.o: modusfor.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmiod/modusfor.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmiod/modsynchronisation.h \ + ../include/dcmtk/dcmiod/modbase.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h +modusfor.o: modusfor.cc ../include/dcmtk/dcmiod/modusfor.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -2682,10 +2663,14 @@ modusfor.o: modusfor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -2709,17 +2694,19 @@ modusfor.o: modusfor.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../ofstd/include/dcmtk/ofstd/oftime.h diff --git a/dcmiod/libsrc/cielabutil.cc b/dcmiod/libsrc/cielabutil.cc index fa4f3154..478a92e0 100644 --- a/dcmiod/libsrc/cielabutil.cc +++ b/dcmiod/libsrc/cielabutil.cc @@ -1,7 +1,6 @@ /* * - * Copyright (C) 2005-2018, Pascal Getreuer - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2005-2019, Pascal Getreuer, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,9 +18,9 @@ * Purpose: Static helper functionality for CIE<->RGB color conversions * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/cielabutil.h" -#define INCLUDE_CMATH // for pow() function +#include "dcmtk/config/osconfig.h" +#define INCLUDE_CMATH // for pow() function #include "dcmtk/ofstd/ofstdinc.h" // workaround for SunPro not defining these C functions in the global namespace @@ -34,181 +33,165 @@ const double IODCIELabUtil::D65_WHITEPOINT_X = 0.950456; const double IODCIELabUtil::D65_WHITEPOINT_Y = 1.0; const double IODCIELabUtil::D65_WHITEPOINT_Z = 1.088754; - void IODCIELabUtil::dicomLab2RGB(double& R, double& G, double& B, double LDicom, double aDicom, double bDicom) { - double L, a, b; - dicomlab2Lab(L, a, b, LDicom, aDicom, bDicom); - lab2Rgb(R, G, B, L, a, b); + double L, a, b; + dicomlab2Lab(L, a, b, LDicom, aDicom, bDicom); + lab2Rgb(R, G, B, L, a, b); } - void IODCIELabUtil::rgb2DicomLab(double& LDicom, double& aDicom, double& bDicom, double R, double G, double B) { - double L, a, b; - rgb2Lab(L, a, b, R, G, B); - lab2DicomLab(LDicom, aDicom, bDicom, L, a, b); + double L, a, b; + rgb2Lab(L, a, b, R, G, B); + lab2DicomLab(LDicom, aDicom, bDicom, L, a, b); } - void IODCIELabUtil::dicomlab2Lab(double& L, double& a, double& b, double LDicom, double aDicom, double bDicom) { - L = ((LDicom * 100.0) / 65535.0); // results in 0 <= L <= 100 - a = ((aDicom * 255.0) / 65535.0) - 128; // results in -128 <= a <= 127 - b = ((bDicom * 255.0) / 65535.0) - 128; // results in -128 <= b <= 127 + L = ((LDicom * 100.0) / 65535.0); // results in 0 <= L <= 100 + a = ((aDicom * 255.0) / 65535.0) - 128; // results in -128 <= a <= 127 + b = ((bDicom * 255.0) / 65535.0) - 128; // results in -128 <= b <= 127 } - void IODCIELabUtil::lab2DicomLab(double& LDicom, double& aDicom, double& bDicom, double L, double a, double b) { - LDicom = L * 65535.0 / 100.0; // results in 0 <= L <= 65535 - aDicom = (a + 128) * 65535.0 / 255.0; // results in 0 <= a <= 65535 - bDicom = (b + 128) * 65535.0 / 255.0; // results in 0 <= b <= 65535 + LDicom = L * 65535.0 / 100.0; // results in 0 <= L <= 65535 + aDicom = (a + 128) * 65535.0 / 255.0; // results in 0 <= a <= 65535 + bDicom = (b + 128) * 65535.0 / 255.0; // results in 0 <= b <= 65535 } - void IODCIELabUtil::rgb2Lab(double& L, double& a, double& b, double R, double G, double B) { - double X, Y, Z; - rgb2Xyz(X, Y, Z, R, G, B); - xyz2Lab(L, a, b, X, Y, Z); + double X, Y, Z; + rgb2Xyz(X, Y, Z, R, G, B); + xyz2Lab(L, a, b, X, Y, Z); } - double IODCIELabUtil::gammaCorrection(double n) { - if ((n) <= 0.0031306684425005883) - { - return 12.92 * (n); - } - else - { - return (1.055*pow((n), 0.416666666666666667) - 0.055); - } + if ((n) <= 0.0031306684425005883) + { + return 12.92 * (n); + } + else + { + return (1.055 * pow((n), 0.416666666666666667) - 0.055); + } } - double IODCIELabUtil::invGammaCorrection(double n) { - if ((n) <= 0.0404482362771076) - { - return ((n) / 12.92); - } - else - { - return ( pow(((n) + 0.055)/1.055, 2.4) ); - } + if ((n) <= 0.0404482362771076) + { + return ((n) / 12.92); + } + else + { + return (pow(((n) + 0.055) / 1.055, 2.4)); + } } - void IODCIELabUtil::rgb2Xyz(double& X, double& Y, double& Z, double R, double G, double B) { - R = invGammaCorrection(R); - G = invGammaCorrection(G); - B = invGammaCorrection(B); - X = OFstatic_cast(double, (0.4123955889674142161*R + 0.3575834307637148171*G + 0.1804926473817015735*B)); - Y = OFstatic_cast(double, (0.2125862307855955516*R + 0.7151703037034108499*G + 0.07220049864333622685*B)); - Z = OFstatic_cast(double, (0.01929721549174694484*R + 0.1191838645808485318*G + 0.9504971251315797660*B)); + R = invGammaCorrection(R); + G = invGammaCorrection(G); + B = invGammaCorrection(B); + X = OFstatic_cast(double, (0.4123955889674142161 * R + 0.3575834307637148171 * G + 0.1804926473817015735 * B)); + Y = OFstatic_cast(double, (0.2125862307855955516 * R + 0.7151703037034108499 * G + 0.07220049864333622685 * B)); + Z = OFstatic_cast(double, (0.01929721549174694484 * R + 0.1191838645808485318 * G + 0.9504971251315797660 * B)); } - void IODCIELabUtil::xyz2Lab(double& L, double& a, double& b, double X, double Y, double Z) { - X /= D65_WHITEPOINT_X; - Y /= D65_WHITEPOINT_Y; - Z /= D65_WHITEPOINT_Z; - X = labf(X); - Y = labf(Y); - Z = labf(Z); - L = 116*Y - 16; - a = 500*(X - Y); - b = 200*(Y - Z); + X /= D65_WHITEPOINT_X; + Y /= D65_WHITEPOINT_Y; + Z /= D65_WHITEPOINT_Z; + X = labf(X); + Y = labf(Y); + Z = labf(Z); + L = 116 * Y - 16; + a = 500 * (X - Y); + b = 200 * (Y - Z); } - void IODCIELabUtil::lab2Rgb(double& R, double& G, double& B, double L, double a, double b) { - double X, Y, Z; - lab2Xyz(X, Y, Z, L, a, b); - xyz2Rgb(R, G, B, X, Y, Z); + double X, Y, Z; + lab2Xyz(X, Y, Z, L, a, b); + xyz2Rgb(R, G, B, X, Y, Z); } - void IODCIELabUtil::lab2Xyz(double& X, double& Y, double& Z, double L, double a, double b) { - L = (L + 16)/116; - a = L + a/500; - b = L - b/200; - X = D65_WHITEPOINT_X * labfInv(a); - Y = D65_WHITEPOINT_Y * labfInv(L); - Z = D65_WHITEPOINT_Z * labfInv(b); + L = (L + 16) / 116; + a = L + a / 500; + b = L - b / 200; + X = D65_WHITEPOINT_X * labfInv(a); + Y = D65_WHITEPOINT_Y * labfInv(L); + Z = D65_WHITEPOINT_Z * labfInv(b); } - void IODCIELabUtil::xyz2Rgb(double& R, double& G, double& B, double X, double Y, double Z) { - double R1, B1, G1, Min; + double R1, B1, G1, Min; - R1 = OFstatic_cast(double, ( 3.2406*X - 1.5372*Y - 0.4986*Z)); - G1 = OFstatic_cast(double, (-0.9689*X + 1.8758*Y + 0.0415*Z)); - B1 = OFstatic_cast(double, ( 0.0557*X - 0.2040*Y + 1.0570*Z)); + R1 = OFstatic_cast(double, (3.2406 * X - 1.5372 * Y - 0.4986 * Z)); + G1 = OFstatic_cast(double, (-0.9689 * X + 1.8758 * Y + 0.0415 * Z)); + B1 = OFstatic_cast(double, (0.0557 * X - 0.2040 * Y + 1.0570 * Z)); - Min = min3(R1, G1, B1); + Min = min3(R1, G1, B1); - /* Force nonnegative values so that gamma correction is well-defined. */ - if(Min < 0) - { - R1 -= Min; - G1 -= Min; - B1 -= Min; - } + /* Force nonnegative values so that gamma correction is well-defined. */ + if (Min < 0) + { + R1 -= Min; + G1 -= Min; + B1 -= Min; + } - /* Transform from RGB to R'G'B' */ - R = gammaCorrection(R1); - G = gammaCorrection(G1); - B = gammaCorrection(B1); + /* Transform from RGB to R'G'B' */ + R = gammaCorrection(R1); + G = gammaCorrection(G1); + B = gammaCorrection(B1); } - double IODCIELabUtil::labf(double n) { - if (n >= 8.85645167903563082e-3) - { - return ( pow(n, 0.333333333333333) ); - } - else - { - return ( (841.0/108.0)*(n) + (4.0/29.0) ); - } + if (n >= 8.85645167903563082e-3) + { + return (pow(n, 0.333333333333333)); + } + else + { + return ((841.0 / 108.0) * (n) + (4.0 / 29.0)); + } } - double IODCIELabUtil::labfInv(double n) { - if ( (n) >= 0.206896551724137931 ) - { - return (n)*(n)*(n); - } - else - { - return (108.0/841.0)*((n) - (4.0/29.0)); - } + if ((n) >= 0.206896551724137931) + { + return (n) * (n) * (n); + } + else + { + return (108.0 / 841.0) * ((n) - (4.0 / 29.0)); + } } - double IODCIELabUtil::min2(double a, double b) { - if (a <= b) - return a; - else - return b; + if (a <= b) + return a; + else + return b; } - double IODCIELabUtil::min3(double a, double b, double c) { - if (a <= b) - return min2(a,c); - else - return min2(b,c); + if (a <= b) + return min2(a, c); + else + return min2(b, c); } diff --git a/dcmiod/libsrc/iodcommn.cc b/dcmiod/libsrc/iodcommn.cc index 06fc3112..3c460873 100644 --- a/dcmiod/libsrc/iodcommn.cc +++ b/dcmiod/libsrc/iodcommn.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,160 +19,143 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodcommn.h" -#include "dcmtk/dcmdata/dctypes.h" // logger +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctypes.h" // logger #include "dcmtk/dcmiod/iodutil.h" - DcmIODCommon::DcmIODCommon() -: m_Item(new DcmItem()), - m_Rules(new IODRules), - m_Patient(m_Item, m_Rules), - m_PatientStudy(m_Item, m_Rules), - m_Study(m_Item, m_Rules), - m_Equipment(m_Item, m_Rules), - m_Series(m_Item, m_Rules), - m_FrameOfReference(m_Item, m_Rules), - m_SOPCommon(m_Item, m_Rules), - m_CommonInstanceReferenceModule(m_Item, m_Rules), - m_Modules() + : m_Item(new DcmItem()) + , m_Rules(new IODRules) + , m_Patient(m_Item, m_Rules) + , m_PatientStudy(m_Item, m_Rules) + , m_Study(m_Item, m_Rules) + , m_Equipment(m_Item, m_Rules) + , m_Series(m_Item, m_Rules) + , m_FrameOfReference(m_Item, m_Rules) + , m_SOPCommon(m_Item, m_Rules) + , m_CommonInstanceReferenceModule(m_Item, m_Rules) + , m_Modules() { - // Set initial values for a new SOP instance - ensureInstanceUIDs(OFFalse); - // push this first so Specific Character Set will be written in the beginning - m_Modules.push_back(&m_SOPCommon); - m_Modules.push_back(&m_Patient); - m_Modules.push_back(&m_PatientStudy); - m_Modules.push_back(&m_Study); - m_Modules.push_back(&m_Equipment); - m_Modules.push_back(&m_Series); - m_Modules.push_back(&m_FrameOfReference); - m_Modules.push_back(&m_CommonInstanceReferenceModule); + // Set initial values for a new SOP instance + ensureInstanceUIDs(OFFalse); + // push this first so Specific Character Set will be written in the beginning + m_Modules.push_back(&m_SOPCommon); + m_Modules.push_back(&m_Patient); + m_Modules.push_back(&m_PatientStudy); + m_Modules.push_back(&m_Study); + m_Modules.push_back(&m_Equipment); + m_Modules.push_back(&m_Series); + m_Modules.push_back(&m_FrameOfReference); + m_Modules.push_back(&m_CommonInstanceReferenceModule); } - DcmIODCommon::DcmIODCommon(const DcmIODCommon& rhs) -: m_Item(rhs.m_Item), - m_Rules(rhs.m_Rules), - m_Patient(m_Item, m_Rules), - m_PatientStudy(m_Item, m_Rules), - m_Study(m_Item, m_Rules), - m_Equipment(m_Item, m_Rules), - m_Series(m_Item, m_Rules), - m_FrameOfReference(m_Item, m_Rules), - m_SOPCommon(m_Item, m_Rules), - m_CommonInstanceReferenceModule(m_Item, m_Rules), - m_Modules() + : m_Item(rhs.m_Item) + , m_Rules(rhs.m_Rules) + , m_Patient(m_Item, m_Rules) + , m_PatientStudy(m_Item, m_Rules) + , m_Study(m_Item, m_Rules) + , m_Equipment(m_Item, m_Rules) + , m_Series(m_Item, m_Rules) + , m_FrameOfReference(m_Item, m_Rules) + , m_SOPCommon(m_Item, m_Rules) + , m_CommonInstanceReferenceModule(m_Item, m_Rules) + , m_Modules() { - // Set initial values for a new SOP instance - ensureInstanceUIDs(OFFalse); - // push this first so Specific Character Set will be written in the beginning - m_Modules.push_back(&m_SOPCommon); - m_Modules.push_back(&m_Patient); - m_Modules.push_back(&m_PatientStudy); - m_Modules.push_back(&m_Study); - m_Modules.push_back(&m_Equipment); - m_Modules.push_back(&m_Series); - m_Modules.push_back(&m_FrameOfReference); - m_Modules.push_back(&m_CommonInstanceReferenceModule); + // Set initial values for a new SOP instance + ensureInstanceUIDs(OFFalse); + // push this first so Specific Character Set will be written in the beginning + m_Modules.push_back(&m_SOPCommon); + m_Modules.push_back(&m_Patient); + m_Modules.push_back(&m_PatientStudy); + m_Modules.push_back(&m_Study); + m_Modules.push_back(&m_Equipment); + m_Modules.push_back(&m_Series); + m_Modules.push_back(&m_FrameOfReference); + m_Modules.push_back(&m_CommonInstanceReferenceModule); } - DcmIODCommon::~DcmIODCommon() { } - void DcmIODCommon::clearData() { - // TODO -// OFVector::iterator it = m_Modules.begin(); -// while (it != m_Modules.end()) -// { -// (*it)->clearData(); -// it++; -// } + // TODO + // OFVector::iterator it = m_Modules.begin(); + // while (it != m_Modules.end()) + // { + // (*it)->clearData(); + // it++; + // } } - IODPatientModule& DcmIODCommon::getPatient() { - return m_Patient; + return m_Patient; } - IODPatientStudyModule& DcmIODCommon::getPatientStudy() { - return m_PatientStudy; + return m_PatientStudy; } - IODGeneralStudyModule& DcmIODCommon::getStudy() { - return m_Study; + return m_Study; } - IODGeneralEquipmentModule& DcmIODCommon::getEquipment() { - return m_Equipment; + return m_Equipment; } - IODGeneralSeriesModule& DcmIODCommon::getSeries() { - return m_Series; + return m_Series; } - IODFoRModule& DcmIODCommon::getFrameOfReference() { - return m_FrameOfReference; + return m_FrameOfReference; } - IODSOPCommonModule& DcmIODCommon::getSOPCommon() { - return m_SOPCommon; + return m_SOPCommon; } - IODCommonInstanceReferenceModule& DcmIODCommon::getCommonInstanceReference() { - return m_CommonInstanceReferenceModule; + return m_CommonInstanceReferenceModule; } - - OFshared_ptr DcmIODCommon::getRules() { - return m_Rules; + return m_Rules; } - OFshared_ptr DcmIODCommon::getData() { - return m_Item; + return m_Item; } - -OFCondition DcmIODCommon::read(DcmItem &dataset) +OFCondition DcmIODCommon::read(DcmItem& dataset) { - /* re-initialize object */ - DcmIODCommon::clearData(); - - OFVector::iterator it = m_Modules.begin(); - while ( it != m_Modules.end() ) - { - (*it)->read(dataset, OFTrue /* clear old data */); - it++; - } - - // we do not report errors here (only logger output) - return EC_Normal; -} + /* re-initialize object */ + DcmIODCommon::clearData(); + OFVector::iterator it = m_Modules.begin(); + while (it != m_Modules.end()) + { + (*it)->read(dataset, OFTrue /* clear old data */); + it++; + } + + // we do not report errors here (only logger output) + return EC_Normal; +} OFCondition DcmIODCommon::importHierarchy(DcmItem& dataset, const OFBool readPatient, @@ -181,53 +164,52 @@ OFCondition DcmIODCommon::importHierarchy(DcmItem& dataset, const OFBool readSeries, const OFBool takeOverCharset) { - if (readPatient) - { - m_Patient.read(dataset, OFFalse /* do not clear old data */); - } - - if (readStudy) - { - m_Study.read(dataset, OFFalse /* do not clear old data */); - m_Equipment.read(dataset, OFFalse /* do not clear old data */); - m_PatientStudy.read(dataset, OFFalse /* do not clear old data */); - } - - if (readSeries) - { - m_Series.read(dataset, OFFalse /* do not clear old data */); - m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); - } - - if (readFoR) - { - m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); - } - - // Take over character set from the dataset imported, if desired - if (takeOverCharset) - { - OFString charset; - dataset.findAndGetOFStringArray(DCM_SpecificCharacterSet, charset); - if (!charset.empty()) + if (readPatient) + { + m_Patient.read(dataset, OFFalse /* do not clear old data */); + } + + if (readStudy) { - DCMIOD_DEBUG("Taking over Specific Character Set " << charset << " on import"); - OFCondition result = m_SOPCommon.setSpecificCharacterSet(charset); - if (result.bad()) - { - DCMIOD_ERROR("Could not set Specific Character Set " << charset << " on import: " << result.text()); - } + m_Study.read(dataset, OFFalse /* do not clear old data */); + m_Equipment.read(dataset, OFFalse /* do not clear old data */); + m_PatientStudy.read(dataset, OFFalse /* do not clear old data */); } - else + + if (readSeries) { - DCMIOD_DEBUG("Taking over Default Specific Character Set (ASCII) on import"); - m_SOPCommon.getData().findAndDeleteElement(DCM_SpecificCharacterSet); + m_Series.read(dataset, OFFalse /* do not clear old data */); + m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); } - } - return EC_Normal; -} + if (readFoR) + { + m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); + } + // Take over character set from the dataset imported, if desired + if (takeOverCharset) + { + OFString charset; + dataset.findAndGetOFStringArray(DCM_SpecificCharacterSet, charset); + if (!charset.empty()) + { + DCMIOD_DEBUG("Taking over Specific Character Set " << charset << " on import"); + OFCondition result = m_SOPCommon.setSpecificCharacterSet(charset); + if (result.bad()) + { + DCMIOD_ERROR("Could not set Specific Character Set " << charset << " on import: " << result.text()); + } + } + else + { + DCMIOD_DEBUG("Taking over Default Specific Character Set (ASCII) on import"); + m_SOPCommon.getData().findAndDeleteElement(DCM_SpecificCharacterSet); + } + } + + return EC_Normal; +} OFCondition DcmIODCommon::importHierarchy(const OFString& filename, const OFBool readPatient, @@ -236,82 +218,76 @@ OFCondition DcmIODCommon::importHierarchy(const OFString& filename, const OFBool readSeries, const OFBool takeOverCharset) { - DcmFileFormat dcmff; - OFCondition result = dcmff.loadFile(filename.c_str()); - if ( result.good() ) - { - DcmDataset *dset = dcmff.getDataset(); - if (dset != NULL) - { - result = importHierarchy(*dset, readPatient, readStudy, readFoR, readSeries, takeOverCharset); - } - else + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(filename.c_str()); + if (result.good()) { - DCMIOD_ERROR("Unable to get dataset from file for copying patient, study, series and/or frame of reference information"); - result = EC_IllegalCall; + DcmDataset* dset = dcmff.getDataset(); + if (dset != NULL) + { + result = importHierarchy(*dset, readPatient, readStudy, readFoR, readSeries, takeOverCharset); + } + else + { + DCMIOD_ERROR("Unable to get dataset from file for copying patient, study, series and/or frame of reference " + "information"); + result = EC_IllegalCall; + } } - } - return result; + return result; } - void DcmIODCommon::ensureInstanceUIDs(const OFBool correctInvalid) { - m_Study.ensureInstanceUID(correctInvalid); - m_Series.ensureInstanceUID(correctInvalid); - m_SOPCommon.ensureInstanceUID(correctInvalid); + m_Study.ensureInstanceUID(correctInvalid); + m_Series.ensureInstanceUID(correctInvalid); + m_SOPCommon.ensureInstanceUID(correctInvalid); } - -OFCondition DcmIODCommon::write(DcmItem &dataset) +OFCondition DcmIODCommon::write(DcmItem& dataset) { - OFCondition result; - - OFVector::iterator it = m_Modules.begin(); - while ( (it != m_Modules.end() && result.good()) ) - { - result = (*it)->write(dataset); - it++; - } - return result; -} + OFCondition result; + OFVector::iterator it = m_Modules.begin(); + while ((it != m_Modules.end() && result.good())) + { + result = (*it)->write(dataset); + it++; + } + return result; +} void DcmIODCommon::createNewStudy(const OFBool clearEquipment) { - // clear all study-related attributes - m_Study.clearData(); - m_PatientStudy.clearData(); - if (clearEquipment) - m_Equipment.clearData(); - // make sure we have a valid Study Instance UID - m_Study.ensureInstanceUID(); - - // reset series- and instance related attributes - createNewSeries(); + // clear all study-related attributes + m_Study.clearData(); + m_PatientStudy.clearData(); + if (clearEquipment) + m_Equipment.clearData(); + // make sure we have a valid Study Instance UID + m_Study.ensureInstanceUID(); + + // reset series- and instance related attributes + createNewSeries(); } - void DcmIODCommon::createNewSeries(const OFBool clearFoR) { - // clear all series-related attributes - m_Series.clearData(); - // create new Series Instance UID - m_Series.ensureInstanceUID(); + // clear all series-related attributes + m_Series.clearData(); + // create new Series Instance UID + m_Series.ensureInstanceUID(); - // clear frame of reference-related attributes if desired - if (clearFoR) - m_FrameOfReference.clearData(); + // clear frame of reference-related attributes if desired + if (clearFoR) + m_FrameOfReference.clearData(); - /* also creates new series (since UID is empty) */ - createNewSOPInstance(); + /* also creates new series (since UID is empty) */ + createNewSOPInstance(); } - void DcmIODCommon::createNewSOPInstance() { - m_SOPCommon.clearData(); - m_SOPCommon.ensureInstanceUID(); + m_SOPCommon.clearData(); + m_SOPCommon.ensureInstanceUID(); } - - diff --git a/dcmiod/libsrc/iodcontentitemmacro.cc b/dcmiod/libsrc/iodcontentitemmacro.cc index a96793cb..4858e06a 100644 --- a/dcmiod/libsrc/iodcontentitemmacro.cc +++ b/dcmiod/libsrc/iodcontentitemmacro.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,796 +20,735 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/ofstd/ofstream.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcvrcs.h" -#include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/ofstd/ofstream.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmiod/iodcontentitemmacro.h" +#include "dcmtk/dcmiod/iodutil.h" const OFString ContentItemMacro::ReferencedSOPSequenceItem::m_ComponentName = "ReferencedSOPSequenceItem"; - ContentItemMacro::ReferencedSOPSequenceItem::ReferencedSOPSequenceItem(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent) -: IODComponent(item, rules, parent), - m_SOPInstanceReferenceMacro() + OFshared_ptr rules, + IODComponent* parent) + : IODComponent(item, rules, parent) + , m_SOPInstanceReferenceMacro() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - ContentItemMacro::ReferencedSOPSequenceItem::ReferencedSOPSequenceItem(IODComponent* parent) -: IODComponent(parent), - m_SOPInstanceReferenceMacro() + : IODComponent(parent) + , m_SOPInstanceReferenceMacro() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - ContentItemMacro::ReferencedSOPSequenceItem::ReferencedSOPSequenceItem(const ReferencedSOPSequenceItem& rhs) -: IODComponent(rhs), - m_SOPInstanceReferenceMacro() + : IODComponent(rhs) + , m_SOPInstanceReferenceMacro() { } - ContentItemMacro::ReferencedSOPSequenceItem::~ReferencedSOPSequenceItem() { - // nothing to do + // nothing to do } - OFString ContentItemMacro::ReferencedSOPSequenceItem::getName() const { - return m_ComponentName; + return m_ComponentName; } - void ContentItemMacro::ReferencedSOPSequenceItem::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_ReferencedFrameNumber, "1-n","1C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedSegmentNumber, "1-n","1C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_ReferencedFrameNumber, "1-n", "1C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSegmentNumber, "1-n", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue); } - -OFCondition ContentItemMacro::ReferencedSOPSequenceItem::read( - DcmItem& source, - const OFBool clearOldData) +OFCondition ContentItemMacro::ReferencedSOPSequenceItem::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - IODComponent::read(source, OFFalse /* data already cleared */); - return EC_Normal; + IODComponent::read(source, OFFalse /* data already cleared */); + return EC_Normal; } - OFCondition ContentItemMacro::ReferencedSOPSequenceItem::write(DcmItem& destination) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - result = IODComponent::write(destination); + result = IODComponent::write(destination); - return result; + return result; } - SOPInstanceReferenceMacro& ContentItemMacro::ReferencedSOPSequenceItem::getSOPInstanceReferenceMacro() { - return m_SOPInstanceReferenceMacro; + return m_SOPInstanceReferenceMacro; } - -OFCondition ContentItemMacro::ReferencedSOPSequenceItem::getReferencedFrameNumber( - OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::ReferencedSOPSequenceItem::getReferencedFrameNumber(OFString& value, + const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ReferencedFrameNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ReferencedFrameNumber, *m_Item, value, pos); } - -OFCondition ContentItemMacro::ReferencedSOPSequenceItem::getReferencedSegmentNumber( - Uint16 &value, - const signed long pos) const +OFCondition ContentItemMacro::ReferencedSOPSequenceItem::getReferencedSegmentNumber(Uint16& value, + const unsigned long pos) const { - return m_Item->findAndGetUint16(DCM_ReferencedSegmentNumber, value, pos); + return m_Item->findAndGetUint16(DCM_ReferencedSegmentNumber, value, pos); } - -OFCondition ContentItemMacro::ReferencedSOPSequenceItem::setReferencedFrameNumber( - const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::ReferencedSOPSequenceItem::setReferencedFrameNumber(const OFString& value, + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ReferencedFrameNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedFrameNumber, value); + return result; } - -OFCondition ContentItemMacro::ReferencedSOPSequenceItem::setReferencedSegmentNumber( - const Uint16 value, - const OFBool checkValue) +OFCondition ContentItemMacro::ReferencedSOPSequenceItem::setReferencedSegmentNumber(const Uint16 value, + const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_ReferencedSegmentNumber, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_ReferencedSegmentNumber, value); } - const OFString ContentItemMacro::m_ModuleName = "ContentItemMacro"; - ContentItemMacro::ContentItemMacro() -: IODComponent(), - m_ConceptNameCodeSequence(), - m_ConceptCodeSequence(), - m_MeasurementUnitsCodeSequence(), - m_ReferencedSOPSequence() + : IODComponent() + , m_ConceptNameCodeSequence() + , m_ConceptCodeSequence() + , m_MeasurementUnitsCodeSequence() + , m_ReferencedSOPSequence() { - resetRules(); + resetRules(); } - -ContentItemMacro::ContentItemMacro(OFshared_ptr item, - OFshared_ptr rules) -: IODComponent(item, rules), - m_ConceptNameCodeSequence(), - m_ConceptCodeSequence(), - m_MeasurementUnitsCodeSequence(), - m_ReferencedSOPSequence() +ContentItemMacro::ContentItemMacro(OFshared_ptr item, OFshared_ptr rules) + : IODComponent(item, rules) + , m_ConceptNameCodeSequence() + , m_ConceptCodeSequence() + , m_MeasurementUnitsCodeSequence() + , m_ReferencedSOPSequence() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - ContentItemMacro::ContentItemMacro(const ContentItemMacro& rhs) -: IODComponent(rhs), - m_ConceptNameCodeSequence(), - m_ConceptCodeSequence(), - m_MeasurementUnitsCodeSequence(), - m_ReferencedSOPSequence() -{ - if (this == &rhs) - return; - - OFVector::const_iterator it = rhs.m_ConceptCodeSequence.begin(); - while (it != rhs.m_ConceptCodeSequence.end()) - { - CodeSequenceMacro* macro = new CodeSequenceMacro(**it); - m_ConceptCodeSequence.push_back(macro); - it++; - } - - it = rhs.m_ConceptNameCodeSequence.begin(); - while (it != rhs.m_ConceptNameCodeSequence.end()) - { - CodeSequenceMacro* macro = new CodeSequenceMacro(**it); - m_ConceptNameCodeSequence.push_back(macro); - it++; - } - - it = rhs.m_MeasurementUnitsCodeSequence.begin(); - while (it != rhs.m_MeasurementUnitsCodeSequence.end()) - { - CodeSequenceMacro* macro = new CodeSequenceMacro(**it); - m_MeasurementUnitsCodeSequence.push_back(macro); - it++; - } - - OFVector::const_iterator m = rhs.m_ReferencedSOPSequence.begin(); - while (m != rhs.m_ReferencedSOPSequence.end()) - { - ReferencedSOPSequenceItem* item = new ReferencedSOPSequenceItem(**m); - m_ReferencedSOPSequence.push_back(item); - m++; - } + : IODComponent(rhs) + , m_ConceptNameCodeSequence() + , m_ConceptCodeSequence() + , m_MeasurementUnitsCodeSequence() + , m_ReferencedSOPSequence() +{ + if (this == &rhs) + return; -} + OFVector::const_iterator it = rhs.m_ConceptCodeSequence.begin(); + while (it != rhs.m_ConceptCodeSequence.end()) + { + CodeSequenceMacro* macro = new CodeSequenceMacro(**it); + m_ConceptCodeSequence.push_back(macro); + it++; + } + + it = rhs.m_ConceptNameCodeSequence.begin(); + while (it != rhs.m_ConceptNameCodeSequence.end()) + { + CodeSequenceMacro* macro = new CodeSequenceMacro(**it); + m_ConceptNameCodeSequence.push_back(macro); + it++; + } + + it = rhs.m_MeasurementUnitsCodeSequence.begin(); + while (it != rhs.m_MeasurementUnitsCodeSequence.end()) + { + CodeSequenceMacro* macro = new CodeSequenceMacro(**it); + m_MeasurementUnitsCodeSequence.push_back(macro); + it++; + } + OFVector::const_iterator m = rhs.m_ReferencedSOPSequence.begin(); + while (m != rhs.m_ReferencedSOPSequence.end()) + { + ReferencedSOPSequenceItem* item = new ReferencedSOPSequenceItem(**m); + m_ReferencedSOPSequence.push_back(item); + m++; + } +} ContentItemMacro::~ContentItemMacro() { - DcmIODUtil::freeContainer(m_ConceptNameCodeSequence); - DcmIODUtil::freeContainer(m_ConceptCodeSequence); - DcmIODUtil::freeContainer(m_MeasurementUnitsCodeSequence); - DcmIODUtil::freeContainer(m_ReferencedSOPSequence); + DcmIODUtil::freeContainer(m_ConceptNameCodeSequence); + DcmIODUtil::freeContainer(m_ConceptCodeSequence); + DcmIODUtil::freeContainer(m_MeasurementUnitsCodeSequence); + DcmIODUtil::freeContainer(m_ReferencedSOPSequence); } - OFString ContentItemMacro::getName() const { - return m_ModuleName; + return m_ModuleName; } - void ContentItemMacro::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_ValueType, "1","1", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ConceptNameCodeSequence, "1","1", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_DateTime, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_Date, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_Time, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_PersonName, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_UID, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_TextValue, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ConceptCodeSequence, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_NumericValue, "1-n","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_FloatingPointValue, "1-n","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_RationalNumeratorValue, "1-n","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_RationalDenominatorValue, "1-n","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedSOPSequence, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); -} - - -OFCondition ContentItemMacro::read(DcmItem& source, - const OFBool clearOldData) -{ - if (clearOldData) - clearData(); - - IODComponent::read(source, OFFalse /* data already cleared */); - DcmIODUtil::readSubSequence(source, DCM_ConceptNameCodeSequence, m_ConceptNameCodeSequence, m_Rules->getByTag(DCM_ConceptNameCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_ConceptCodeSequence, m_ConceptCodeSequence, m_Rules->getByTag(DCM_ConceptCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCodeSequence, m_Rules->getByTag(DCM_MeasurementUnitsCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_ReferencedSOPSequence, m_ReferencedSOPSequence, m_Rules->getByTag(DCM_ReferencedSOPSequence)); - - return EC_Normal; + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_ValueType, "1", "1", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ConceptNameCodeSequence, "1", "1", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_DateTime, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_Date, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_Time, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PersonName, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_UID, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_TextValue, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ConceptCodeSequence, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_NumericValue, "1-n", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_FloatingPointValue, "1-n", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_RationalNumeratorValue, "1-n", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_RationalDenominatorValue, "1-n", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1", "1C", getName(), DcmIODTypes::IE_SERIES), + OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPSequence, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); +} + +OFCondition ContentItemMacro::read(DcmItem& source, const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + IODComponent::read(source, OFFalse /* data already cleared */); + DcmIODUtil::readSubSequence( + source, DCM_ConceptNameCodeSequence, m_ConceptNameCodeSequence, m_Rules->getByTag(DCM_ConceptNameCodeSequence)); + DcmIODUtil::readSubSequence( + source, DCM_ConceptCodeSequence, m_ConceptCodeSequence, m_Rules->getByTag(DCM_ConceptCodeSequence)); + DcmIODUtil::readSubSequence(source, + DCM_MeasurementUnitsCodeSequence, + m_MeasurementUnitsCodeSequence, + m_Rules->getByTag(DCM_MeasurementUnitsCodeSequence)); + DcmIODUtil::readSubSequence( + source, DCM_ReferencedSOPSequence, m_ReferencedSOPSequence, m_Rules->getByTag(DCM_ReferencedSOPSequence)); + + return EC_Normal; } - OFCondition ContentItemMacro::write(DcmItem& destination) { - OFCondition result = EC_Normal; - - if(CodeSequenceMacro* pConceptNameCodeSequence = getConceptNameCodeSequence()) - DcmIODUtil::writeSingleItem(result, DCM_ConceptNameCodeSequence, *pConceptNameCodeSequence, *m_Item, m_Rules->getByTag(DCM_ConceptNameCodeSequence)); - if(CodeSequenceMacro* pConceptCodeSequence = getConceptCodeSequence()) - DcmIODUtil::writeSingleItem(result, DCM_ConceptCodeSequence, *pConceptCodeSequence, *m_Item, m_Rules->getByTag(DCM_ConceptCodeSequence)); - if(CodeSequenceMacro* pMeasurementUnitsCodeSequence = getMeasurementUnitsCodeSequence()) - DcmIODUtil::writeSingleItem(result, DCM_MeasurementUnitsCodeSequence, *pMeasurementUnitsCodeSequence, *m_Item, m_Rules->getByTag(DCM_MeasurementUnitsCodeSequence)); - if(ReferencedSOPSequenceItem* pReferencedSOPSequence = getReferencedSOPSequence()) - DcmIODUtil::writeSingleItem(result, DCM_ReferencedSOPSequence, *pReferencedSOPSequence, *m_Item, m_Rules->getByTag(DCM_ReferencedSOPSequence)); - - if (result.good()) - { - result = IODComponent::write(destination); - } + OFCondition result = EC_Normal; + + if (CodeSequenceMacro* pConceptNameCodeSequence = getConceptNameCodeSequence()) + DcmIODUtil::writeSingleItem(result, + DCM_ConceptNameCodeSequence, + *pConceptNameCodeSequence, + *m_Item, + m_Rules->getByTag(DCM_ConceptNameCodeSequence)); + if (CodeSequenceMacro* pConceptCodeSequence = getConceptCodeSequence()) + DcmIODUtil::writeSingleItem(result, + DCM_ConceptCodeSequence, + *pConceptCodeSequence, + *m_Item, + m_Rules->getByTag(DCM_ConceptCodeSequence)); + if (CodeSequenceMacro* pMeasurementUnitsCodeSequence = getMeasurementUnitsCodeSequence()) + DcmIODUtil::writeSingleItem(result, + DCM_MeasurementUnitsCodeSequence, + *pMeasurementUnitsCodeSequence, + *m_Item, + m_Rules->getByTag(DCM_MeasurementUnitsCodeSequence)); + if (ReferencedSOPSequenceItem* pReferencedSOPSequence = getReferencedSOPSequence()) + DcmIODUtil::writeSingleItem(result, + DCM_ReferencedSOPSequence, + *pReferencedSOPSequence, + *m_Item, + m_Rules->getByTag(DCM_ReferencedSOPSequence)); + + if (result.good()) + { + result = IODComponent::write(destination); + } - return result; + return result; } - -OFCondition ContentItemMacro::getValueType(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getValueType(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ValueType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ValueType, *m_Item, value, pos); } - OFCondition ContentItemMacro::getValueType(ValueType& value) const { - OFString str; - OFCondition result = DcmIODUtil::getStringValueFromItem(DCM_ValueType, *m_Item, str, 0); - if (result == EC_Normal) - { - if (!str.empty()) + OFString str; + OFCondition result = DcmIODUtil::getStringValueFromItem(DCM_ValueType, *m_Item, str, 0); + if (result == EC_Normal) { - if (str == "DATE") - value = VT_DATE; - else if (str == "TIME") - value = VT_TIME; - else if (str == "DATETIME") - value = VT_DATETIME; - else if (str == "PNAME") - value = VT_PNAME; - else if (str == "UIDREF") - value = VT_UIDREF; - else if (str == "TEXT") - value = VT_TEXT; - else if (str == "CODE") - value = VT_CODE; - else if (str == "NUMERIC") - value = VT_NUMERIC; - else if (str == "COMPOSITE") - value = VT_COMPOSITE; - else if (str == "IMAGE") - value = VT_IMAGE; - else - value = VT_UNKNOWN; + if (!str.empty()) + { + if (str == "DATE") + value = VT_DATE; + else if (str == "TIME") + value = VT_TIME; + else if (str == "DATETIME") + value = VT_DATETIME; + else if (str == "PNAME") + value = VT_PNAME; + else if (str == "UIDREF") + value = VT_UIDREF; + else if (str == "TEXT") + value = VT_TEXT; + else if (str == "CODE") + value = VT_CODE; + else if (str == "NUMERIC") + value = VT_NUMERIC; + else if (str == "COMPOSITE") + value = VT_COMPOSITE; + else if (str == "IMAGE") + value = VT_IMAGE; + else + value = VT_UNKNOWN; + } + else + { + value = VT_EMPTY; + } + } + else if (result == EC_TagNotFound) + { + value = VT_EMPTY; } else { - value = VT_EMPTY; + DCMIOD_ERROR("Unexpected error, could not get Value Type: " << result.text()); + value = VT_UNKNOWN; } - } - else if (result == EC_TagNotFound) - { - value = VT_EMPTY; - } - else - { - DCMIOD_ERROR("Unexpected error, could not get Value Type: " << result.text()); - value = VT_UNKNOWN; - } - return result; + return result; } - CodeSequenceMacro* ContentItemMacro::getConceptNameCodeSequence() { - return m_ConceptNameCodeSequence.empty() ? OFnullptr : *m_ConceptNameCodeSequence.begin(); + return m_ConceptNameCodeSequence.empty() ? OFnullptr : *m_ConceptNameCodeSequence.begin(); } OFVector& ContentItemMacro::getEntireConceptNameCodeSequence() { - return m_ConceptNameCodeSequence; + return m_ConceptNameCodeSequence; } - -OFCondition ContentItemMacro::getDateTime(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getDateTime(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DateTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DateTime, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getDate(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getDate(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Date, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Date, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getTime(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getTime(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Time, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Time, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getPersonName(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getPersonName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PersonName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PersonName, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getUID(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getUID(OFString& value, const signed long pos) const { - return m_Item->findAndGetOFString(DCM_UID, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_UID, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getTextValue(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getTextValue(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_TextValue, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TextValue, *m_Item, value, pos); } - CodeSequenceMacro* ContentItemMacro::getConceptCodeSequence() { - return m_ConceptCodeSequence.empty() ? OFnullptr : *m_ConceptCodeSequence.begin(); + return m_ConceptCodeSequence.empty() ? OFnullptr : *m_ConceptCodeSequence.begin(); } OFVector& ContentItemMacro::getEntireConceptCodeSequence() { - return m_ConceptCodeSequence; + return m_ConceptCodeSequence; } - -OFCondition ContentItemMacro::getNumericValue(OFString &value, - const signed long pos) const +OFCondition ContentItemMacro::getNumericValue(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_NumericValue, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_NumericValue, *m_Item, value, pos); } - -OFCondition ContentItemMacro::getFloatingPointValue(Float64 &value, - const signed long pos) const +OFCondition ContentItemMacro::getFloatingPointValue(Float64& value, const unsigned long pos) const { - return m_Item->findAndGetFloat64(DCM_FloatingPointValue, value, pos); + return m_Item->findAndGetFloat64(DCM_FloatingPointValue, value, pos); } - -OFCondition ContentItemMacro::getRationalNumeratorValue(Sint32 &value, - const signed long pos) const +OFCondition ContentItemMacro::getRationalNumeratorValue(Sint32& value, const unsigned long pos) const { - return m_Item->findAndGetSint32(DCM_RationalNumeratorValue, value, pos); + return m_Item->findAndGetSint32(DCM_RationalNumeratorValue, value, pos); } - -OFCondition ContentItemMacro::getRationalDenominatorValue(Uint32 &value, - const signed long pos) const +OFCondition ContentItemMacro::getRationalDenominatorValue(Uint32& value, const unsigned long pos) const { - return m_Item->findAndGetUint32(DCM_RationalDenominatorValue, value, pos); + return m_Item->findAndGetUint32(DCM_RationalDenominatorValue, value, pos); } - CodeSequenceMacro* ContentItemMacro::getMeasurementUnitsCodeSequence() { - return m_MeasurementUnitsCodeSequence.empty() ? OFnullptr : *m_MeasurementUnitsCodeSequence.begin(); + return m_MeasurementUnitsCodeSequence.empty() ? OFnullptr : *m_MeasurementUnitsCodeSequence.begin(); } OFVector& ContentItemMacro::getEntireMeasurementUnitsCodeSequence() { - return m_MeasurementUnitsCodeSequence; + return m_MeasurementUnitsCodeSequence; } - ContentItemMacro::ReferencedSOPSequenceItem* ContentItemMacro::getReferencedSOPSequence() { - return m_ReferencedSOPSequence.empty() ? OFnullptr : *m_ReferencedSOPSequence.begin(); + return m_ReferencedSOPSequence.empty() ? OFnullptr : *m_ReferencedSOPSequence.begin(); } OFVector& ContentItemMacro::getEntireReferencedSOPSequence() { - return m_ReferencedSOPSequence; + return m_ReferencedSOPSequence; } - -OFCondition ContentItemMacro::setValueType(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setValueType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, value); + return result; } - -OFCondition ContentItemMacro::setValueType(const ContentItemMacro::ValueType value, - const OFBool checkValue) +OFCondition ContentItemMacro::setValueType(const ContentItemMacro::ValueType value, const OFBool checkValue) { - (void)checkValue; - OFCondition result; - switch (value) - { - case VT_DATE: + (void)checkValue; + OFCondition result; + switch (value) { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "DATE"); - break; - } - case VT_TIME: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "TIME"); - break; - } - case VT_DATETIME: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "DATETIME"); - break; - } - case VT_PNAME: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "PNAME"); - break; - } - case VT_UIDREF: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "UIDREF"); - break; - } - case VT_TEXT: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "TEXT"); - break; - } - case VT_CODE: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "CODE"); - break; - } - case VT_NUMERIC: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "NUMERIC"); - break; - } - case VT_COMPOSITE: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "COMPOSITE"); - break; - } - case VT_IMAGE: - { - result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "IMAGE"); - break; - } - default: - { - result = IOD_EC_InvalidElementValue; + case VT_DATE: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "DATE"); + break; + } + case VT_TIME: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "TIME"); + break; + } + case VT_DATETIME: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "DATETIME"); + break; + } + case VT_PNAME: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "PNAME"); + break; + } + case VT_UIDREF: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "UIDREF"); + break; + } + case VT_TEXT: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "TEXT"); + break; + } + case VT_CODE: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "CODE"); + break; + } + case VT_NUMERIC: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "NUMERIC"); + break; + } + case VT_COMPOSITE: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "COMPOSITE"); + break; + } + case VT_IMAGE: + { + result = m_Item->putAndInsertOFStringArray(DCM_ValueType, "IMAGE"); + break; + } + default: + { + result = IOD_EC_InvalidElementValue; + } } - } - return result; + return result; } - - -OFCondition ContentItemMacro::setDateTime(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setDateTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DateTime, value); - return result; + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DateTime, value); + return result; } - -OFCondition ContentItemMacro::setDate(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_Date, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Date, value); + return result; } - -OFCondition ContentItemMacro::setTime(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_Time, value); - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Time, value); + return result; } - -OFCondition ContentItemMacro::setPersonName(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setPersonName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PersonName, value); - return result; + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PersonName, value); + return result; } - -OFCondition ContentItemMacro::setUID(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setUID(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertOFStringArray(DCM_UID, value); + (void)checkValue; + return m_Item->putAndInsertOFStringArray(DCM_UID, value); } - -OFCondition ContentItemMacro::setTextValue(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setTextValue(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUnlimitedText::checkStringValue(value) : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_TextValue, value); - return result; + OFCondition result = (checkValue) ? DcmUnlimitedText::checkStringValue(value) : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TextValue, value); + return result; } - -OFCondition ContentItemMacro::setNumericValue(const OFString &value, - const OFBool checkValue) +OFCondition ContentItemMacro::setNumericValue(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_NumericValue, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_NumericValue, value); + return result; } - -OFCondition ContentItemMacro::setFloatingPointValue(const Float64 value, - const unsigned long pos, - const OFBool checkValue) +OFCondition +ContentItemMacro::setFloatingPointValue(const Float64 value, const unsigned long pos, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_FloatingPointValue, value, pos); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_FloatingPointValue, value, pos); } - -OFCondition ContentItemMacro::setRationalNumeratorValue(const Sint32 value, - const unsigned long pos, - const OFBool checkValue) +OFCondition +ContentItemMacro::setRationalNumeratorValue(const Sint32 value, const unsigned long pos, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertSint32(DCM_RationalNumeratorValue, value, pos); + (void)checkValue; + return m_Item->putAndInsertSint32(DCM_RationalNumeratorValue, value, pos); } - -OFCondition ContentItemMacro::setRationalDenominatorValue(const Uint32 value, - const unsigned long pos, - const OFBool checkValue) +OFCondition +ContentItemMacro::setRationalDenominatorValue(const Uint32 value, const unsigned long pos, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint32(DCM_RationalDenominatorValue, value, pos); + (void)checkValue; + return m_Item->putAndInsertUint32(DCM_RationalDenominatorValue, value, pos); } - OFString ContentItemMacro::toString() { - ValueType vt; - getValueType(vt); - OFStringStream oss; - if (getConceptNameCodeSequence()) - { - oss << getConceptNameCodeSequence()->toString() << ": "; - } - else - { - oss << ": "; - } - switch (vt) - { - case VT_CODE: - oss << "CODE: " << getConceptCodeSequence()->toString(); - break; - case VT_COMPOSITE: + ValueType vt; + getValueType(vt); + OFStringStream oss; + if (getConceptNameCodeSequence()) { - OFString sopClass, sopInstance, frameNumber; - if (getReferencedSOPSequence()) - { - getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopClass); - getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopInstance); - getReferencedSOPSequence()->getReferencedFrameNumber(frameNumber); - oss << "COMPOSITE: " << sopClass << " / " << sopInstance; - if (!frameNumber.empty()) - { - oss << " / Frames: " << frameNumber; - } - Uint16 val,pos; - val = pos = 0; - if (getReferencedSOPSequence()->getReferencedSegmentNumber(val, pos).good()) - { - oss << " / Segments: "; - while (getReferencedSOPSequence()->getReferencedSegmentNumber(val, pos).good()) - { - oss << val << " "; - pos++; - } - } - } - else - { - oss << "COMPOSITE: "; - } - break; + oss << getConceptNameCodeSequence()->toString() << ": "; } - case VT_DATE: - { - OFString date; - getDate(date); - oss << "DATE: " << date; - break; - } - case VT_DATETIME: + else { - OFString datetime; - getDateTime(datetime); - oss << "DATETIME: " << datetime; - break; + oss << ": "; } - case VT_IMAGE: + switch (vt) { - OFString sopClass, sopInstance, frameNumber; - if (getReferencedSOPSequence()) - { - getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopClass); - getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopInstance); - getReferencedSOPSequence()->getReferencedFrameNumber(frameNumber); - oss << "IMAGE: " << sopClass << " / " << sopInstance; - if (!frameNumber.empty()) + case VT_CODE: + oss << "CODE: " << getConceptCodeSequence()->toString(); + break; + case VT_COMPOSITE: { - oss << " / Frames: " << frameNumber; + OFString sopClass, sopInstance, frameNumber; + if (getReferencedSOPSequence()) + { + getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopClass); + getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopInstance); + getReferencedSOPSequence()->getReferencedFrameNumber(frameNumber); + oss << "COMPOSITE: " << sopClass << " / " << sopInstance; + if (!frameNumber.empty()) + { + oss << " / Frames: " << frameNumber; + } + Uint16 val, pos; + val = pos = 0; + if (getReferencedSOPSequence()->getReferencedSegmentNumber(val, pos).good()) + { + oss << " / Segments: "; + while (getReferencedSOPSequence()->getReferencedSegmentNumber(val, pos).good()) + { + oss << val << " "; + pos++; + } + } + } + else + { + oss << "COMPOSITE: "; + } + break; } - } - else - { - oss << "IMAGE: "; - } - break; - } - case VT_NUMERIC: - { - OFString val; - getNumericValue(val); - oss << "NUMERIC: " << val; - if (getMeasurementUnitsCodeSequence()) - { - oss << ", Units: " << getMeasurementUnitsCodeSequence()->toString() << ")"; - } - Uint16 pos =0; - Float64 fl64 = 0; - if (getFloatingPointValue(fl64, pos).good()) - { - oss << ", Float value(s): " ; - do + case VT_DATE: { - oss << val << " "; - pos++; - } while (getFloatingPointValue(fl64, pos).good()); - } - else - { - oss << ", Float value(s): "; - } - pos = 0; - Sint32 si32 = 0; - if (getRationalNumeratorValue(si32, pos).good()) - { - oss << ", Numerator value(s): " ; - do + OFString date; + getDate(date); + oss << "DATE: " << date; + break; + } + case VT_DATETIME: { - oss << val << " "; - pos++; - } while (getRationalNumeratorValue(si32, pos).good()); - } - pos = 0; - Uint32 ui32 = 0; - if (getRationalDenominatorValue(ui32, pos).good()) - { - oss << ", Denominator value(s): " ; - do + OFString datetime; + getDateTime(datetime); + oss << "DATETIME: " << datetime; + break; + } + case VT_IMAGE: { - oss << val << " "; - pos++; - } while (getRationalDenominatorValue(ui32, pos).good()); - } - - break; - } - case VT_PNAME: - { - OFString val; - getPersonName(val); - oss << "PNAME: " << val; - break; - } - case VT_TEXT: - { - OFString val; - getTextValue(val); - oss << "TEXT: " << val; - break; - } - case VT_TIME: - { - OFString val; - getTime(val); - oss << "TIME: " << val; - break; - } - case VT_UIDREF: - { - OFString val; - getUID(val); - oss << "UIDREF: " << val; - break; - } - case VT_EMPTY: - { - oss << ""; - break; - } - case VT_UNKNOWN: - { - OFString val; - getValueType(val); - oss << ""; - break; - } - default: - { - oss << ""; + OFString sopClass, sopInstance, frameNumber; + if (getReferencedSOPSequence()) + { + getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopClass); + getReferencedSOPSequence()->getSOPInstanceReferenceMacro().getReferencedSOPClassUID(sopInstance); + getReferencedSOPSequence()->getReferencedFrameNumber(frameNumber); + oss << "IMAGE: " << sopClass << " / " << sopInstance; + if (!frameNumber.empty()) + { + oss << " / Frames: " << frameNumber; + } + } + else + { + oss << "IMAGE: "; + } + break; + } + case VT_NUMERIC: + { + OFString val; + getNumericValue(val); + oss << "NUMERIC: " << val; + if (getMeasurementUnitsCodeSequence()) + { + oss << ", Units: " << getMeasurementUnitsCodeSequence()->toString() << ")"; + } + Uint16 pos = 0; + Float64 fl64 = 0; + if (getFloatingPointValue(fl64, pos).good()) + { + oss << ", Float value(s): "; + do + { + oss << val << " "; + pos++; + } while (getFloatingPointValue(fl64, pos).good()); + } + else + { + oss << ", Float value(s): "; + } + pos = 0; + Sint32 si32 = 0; + if (getRationalNumeratorValue(si32, pos).good()) + { + oss << ", Numerator value(s): "; + do + { + oss << val << " "; + pos++; + } while (getRationalNumeratorValue(si32, pos).good()); + } + pos = 0; + Uint32 ui32 = 0; + if (getRationalDenominatorValue(ui32, pos).good()) + { + oss << ", Denominator value(s): "; + do + { + oss << val << " "; + pos++; + } while (getRationalDenominatorValue(ui32, pos).good()); + } + + break; + } + case VT_PNAME: + { + OFString val; + getPersonName(val); + oss << "PNAME: " << val; + break; + } + case VT_TEXT: + { + OFString val; + getTextValue(val); + oss << "TEXT: " << val; + break; + } + case VT_TIME: + { + OFString val; + getTime(val); + oss << "TIME: " << val; + break; + } + case VT_UIDREF: + { + OFString val; + getUID(val); + oss << "UIDREF: " << val; + break; + } + case VT_EMPTY: + { + oss << ""; + break; + } + case VT_UNKNOWN: + { + OFString val; + getValueType(val); + oss << ""; + break; + } + default: + { + oss << ""; + } } - } - OFSTRINGSTREAM_GETOFSTRING(oss, val); - return val; + OFSTRINGSTREAM_GETOFSTRING(oss, val); + return val; } - diff --git a/dcmiod/libsrc/iodmacro.cc b/dcmiod/libsrc/iodmacro.cc index e171bfd1..c93e2108 100644 --- a/dcmiod/libsrc/iodmacro.cc +++ b/dcmiod/libsrc/iodmacro.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2019, Open Connections GmbH + * Copyright (C) 2015-2020, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,1868 +19,1758 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodmacro.h" -#include "dcmtk/dcmiod/iodutil.h" // for static IOD helpers +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/iodutil.h" // for static IOD helpers #include "dcmtk/ofstd/ofstream.h" - // --------------------------- Code Sequence Macro --------------------------- - // -- Code Sequence Macro -CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent) - : IODComponent(item, rules, parent) +CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent) + : IODComponent(item, rules, parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - -CodeSequenceMacro::CodeSequenceMacro(IODComponent* parent) : IODComponent(parent) +CodeSequenceMacro::CodeSequenceMacro(IODComponent* parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - CodeSequenceMacro::CodeSequenceMacro(const CodeSequenceMacro& rhs) -: IODComponent(rhs) + : IODComponent(rhs) { } - - CodeSequenceMacro::~CodeSequenceMacro() { - // nothing to do + // nothing to do } - CodeSequenceMacro::CodeSequenceMacro(const OFString& codeValue, const OFString& codingSchemeDesignator, const OFString& codeMeaning, const OFString& codingSchemeVersion, IODComponent* parent) -: IODComponent(parent) + : IODComponent(parent) +{ + // reset element rules + resetRules(); + set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion); +} + +OFCondition CodeSequenceMacro::check(const bool quiet) { - // reset element rules - resetRules(); - setCodeValue(codeValue); - setCodeMeaning(codeMeaning); - setCodingSchemeDesignator(codingSchemeDesignator); - if (!codingSchemeVersion.empty()) - { - setCodingSchemeVersion(codingSchemeVersion); - } + OFString val; + getCodeValue(val); + if (!val.empty()) + getCodingSchemeDesignator(val); + if (!val.empty()) + getCodeMeaning(val); + if (!val.empty()) + return EC_Normal; + + return EC_IllegalParameter; } -CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, +CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr item, + OFshared_ptr rules, IODComponent* parent, const OFString& codeValue, const OFString& codingSchemeDesignator, const OFString& codeMeaning, const OFString& codingSchemeVersion) -: IODComponent(item, rules, parent) + : IODComponent(item, rules, parent) { - // reset element rules - resetRules(); - setCodeValue(codeValue); - setCodeMeaning(codeMeaning); - setCodingSchemeDesignator(codingSchemeDesignator); - if (!codingSchemeVersion.empty()) - { - setCodingSchemeVersion(codingSchemeVersion); - } + // reset element rules + resetRules(); + set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion); } - OFString CodeSequenceMacro::getName() const { - return "CodeSequenceMacro"; + return "CodeSequenceMacro"; } - void CodeSequenceMacro::resetRules() { - m_Rules->addRule(new IODRule(DCM_CodeValue, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); - m_Rules->addRule(new IODRule(DCM_CodingSchemeDesignator, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); - m_Rules->addRule(new IODRule(DCM_CodingSchemeVersion, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); - m_Rules->addRule(new IODRule(DCM_CodeMeaning, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_URNCodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_LongCodeValue, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodingSchemeDesignator, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodingSchemeVersion, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodeMeaning, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue /*overwrite old rule*/); } - // -- get dicom attributes -- -OFCondition CodeSequenceMacro::getCodeValue(OFString &value, - const signed long pos) +OFCondition CodeSequenceMacro::getCodeValue(OFString& value, const signed long pos, const OFBool autoTag) { - return DcmIODUtil::getStringValueFromItem(DCM_CodeValue, *m_Item, value, pos); -} + OFString c; + OFCondition cond = DcmIODUtil::getStringValueFromItem(DCM_CodeValue, *m_Item, value, pos); + if (cond.good() || ((cond == EC_TagNotFound) && !autoTag)) + return cond; + cond = DcmIODUtil::getStringValueFromItem(DCM_URNCodeValue, *m_Item, value, pos); + if (cond != EC_TagNotFound) + return cond; -OFCondition CodeSequenceMacro::getCodingSchemeDesignator(OFString &value, - const signed long pos) -{ - return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeDesignator, *m_Item, value, pos); + cond = DcmIODUtil::getStringValueFromItem(DCM_LongCodeValue, *m_Item, value, pos); + return cond; } - -OFCondition CodeSequenceMacro::getCodingSchemeVersion(OFString &value, - const signed long pos) +OFCondition CodeSequenceMacro::getURNCodeValue(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeVersion, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_URNCodeValue, *m_Item, value, pos); +} +OFCondition CodeSequenceMacro::getLongCodeValue(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LongCodeValue, *m_Item, value, pos); } +OFCondition CodeSequenceMacro::getCodingSchemeDesignator(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeDesignator, *m_Item, value, pos); +} -OFCondition CodeSequenceMacro::getCodeMeaning(OFString &value, - const signed long pos) +OFCondition CodeSequenceMacro::getCodingSchemeVersion(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_CodeMeaning, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeVersion, *m_Item, value, pos); } +OFCondition CodeSequenceMacro::getCodeMeaning(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodeMeaning, *m_Item, value, pos); +} OFBool CodeSequenceMacro::empty() { - OFString val; - getCodeValue(val); - if (val.empty()) - { - getCodingSchemeDesignator(val); + OFString val; + getCodeValue(val); if (val.empty()) { - getCodingSchemeVersion(val); - if (val.empty()) - { getCodingSchemeDesignator(val); if (val.empty()) { - return OFTrue; + getCodingSchemeVersion(val); + if (val.empty()) + { + getCodingSchemeDesignator(val); + if (val.empty()) + { + return OFTrue; + } + } } - } } - } - return OFFalse; + return OFFalse; } - // -- set dicom attributes -- -OFCondition CodeSequenceMacro::setCodeValue(const OFString &value, - const OFBool checkValue) +OFCondition CodeSequenceMacro::setCodeValue(const OFString& value, const OFBool checkValue, const OFBool autoTag) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) + OFCondition result; + + // Identify the code value tag to be used + if (autoTag) + { + if ((value.find("://") != OFString_npos) || (value.compare(0, 4, "urn:") == 0)) + { + return setURNCodeValue(value, checkValue); + } + else if (value.length() > 16) // Long Code Value + { + return setLongCodeValue(value, checkValue); + } + } + // Classic Code Value + result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.bad()) + return result; + // TODO: Should check length in characters (not bytes), since SH permits usage of + // non-ASCII characters (i.e. as defined in 0008,0015). + if (value.length() > 16) + return EC_MaximumLengthViolated; result = m_Item->putAndInsertOFStringArray(DCM_CodeValue, value); - return result; + if (result.good()) + { + deleteUnusedCodeValues(DCM_CodeValue); + } + return result; } -OFCondition CodeSequenceMacro::setCodingSchemeDesignator(const OFString &value, - const OFBool checkValue) +OFCondition CodeSequenceMacro::setURNCodeValue(const OFString& value, const bool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeDesignator, value); - return result; + OFCondition result = (checkValue) ? DcmUniversalResourceIdentifierOrLocator::checkStringValue(value) : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_URNCodeValue, value); + if (result.good()) + { + deleteUnusedCodeValues(DCM_URNCodeValue); + } + return result; } -OFCondition CodeSequenceMacro::setCodingSchemeVersion(const OFString &value, - const OFBool checkValue) +OFCondition CodeSequenceMacro::setLongCodeValue(const OFString& value, const bool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1C") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeVersion, value); - return result; + OFCondition result = (checkValue) ? DcmUnlimitedCharacters::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LongCodeValue, value); + if (result.good()) + { + deleteUnusedCodeValues(DCM_LongCodeValue); + } + return result; } -OFCondition CodeSequenceMacro::setCodeMeaning(const OFString &value, - const OFBool checkValue) +OFCondition CodeSequenceMacro::setCodingSchemeDesignator(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_CodeMeaning, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeDesignator, value); + return result; } +OFCondition CodeSequenceMacro::setCodingSchemeVersion(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeVersion, value); + return result; +} + +OFCondition CodeSequenceMacro::setCodeMeaning(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodeMeaning, value); + return result; +} OFCondition CodeSequenceMacro::set(const OFString& value, const OFString& scheme, const OFString& meaning, const OFString& schemeVersion, - const OFBool checkValue) + const OFBool checkValue, + const OFBool autoTag) { - if (checkValue) - { - if (value.empty() || scheme.empty() || meaning.empty() ) - { - DCMIOD_ERROR("Could not set code since Code Value, Coding Scheme Designator and Code Meaning must have non-empty values"); - return IOD_EC_InvalidElementValue; - } - } - OFCondition result = setCodeValue(value, checkValue); - if (result.good()) result = setCodingSchemeDesignator(scheme, checkValue); - if (result.good()) result = setCodeMeaning(meaning, checkValue); - if (result.good() && !schemeVersion.empty()) result = setCodingSchemeVersion(schemeVersion, checkValue); - return result; + OFCondition result; + result = setCodeValue(value, checkValue, autoTag); + if (result.good()) + result = setCodingSchemeDesignator(scheme, checkValue); + if (result.good()) + result = setCodeMeaning(meaning, checkValue); + if (result.good() && !schemeVersion.empty()) + result = setCodingSchemeVersion(schemeVersion, checkValue); + return result; } +void CodeSequenceMacro::deleteUnusedCodeValues(const DcmTagKey& keepTag) +{ + if (keepTag != DCM_CodeValue) + m_Item->findAndDeleteElement(DCM_CodeValue); + if (keepTag != DCM_URNCodeValue) + m_Item->findAndDeleteElement(DCM_URNCodeValue); + if (keepTag != DCM_LongCodeValue) + m_Item->findAndDeleteElement(DCM_LongCodeValue); +} // ---------------------- CodeWithModifiers---------------------- CodeWithModifiers::CodeWithModifiers(const OFString& modifierType, const OFString& modifierVM, const DcmTagKey& modifierSeq) -: CodeSequenceMacro(), - m_Modifiers(), - m_ModifierType(modifierType), - m_ModifierVM(modifierVM), - m_CodeModifierSeq(modifierSeq) + : CodeSequenceMacro() + , m_Modifiers() + , m_ModifierType(modifierType) + , m_ModifierVM(modifierVM) + , m_CodeModifierSeq(modifierSeq) { - resetRules(); + resetRules(); } - CodeWithModifiers::CodeWithModifiers(const CodeWithModifiers& rhs) -: CodeSequenceMacro(rhs), - m_Modifiers(), - m_ModifierType(), - m_ModifierVM(), - m_CodeModifierSeq() + : CodeSequenceMacro(rhs) + , m_Modifiers() + , m_ModifierType() + , m_ModifierVM() + , m_CodeModifierSeq() { - if (&rhs == this) - return; + if (&rhs == this) + return; - *this = rhs; + *this = rhs; } - CodeWithModifiers& CodeWithModifiers::operator=(const CodeWithModifiers& rhs) { - if (&rhs == this) - return *this; + if (&rhs == this) + return *this; - CodeSequenceMacro::operator=(rhs); + CodeSequenceMacro::operator=(rhs); - const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs); - if (r) - { - OFVector::const_iterator it = r->m_Modifiers.begin(); - while ((it != r->m_Modifiers.end())) + const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs); + if (r) { - m_Modifiers.push_back(new CodeSequenceMacro(*it)); - it++; + OFVector::const_iterator it = r->m_Modifiers.begin(); + while ((it != r->m_Modifiers.end())) + { + m_Modifiers.push_back(new CodeSequenceMacro(*it)); + it++; + } } - } - return *this; + return *this; } - OFCondition CodeWithModifiers::check(const OFBool quiet) { - OFCondition result = CodeSequenceMacro::check(quiet); - if (result.good()) - { - OFVector::iterator it = m_Modifiers.begin(); - while (result.good() && (it != m_Modifiers.end())) + OFCondition result = CodeSequenceMacro::check(quiet); + if (result.good()) { - result = (*it)->check(quiet); - it++; + OFVector::iterator it = m_Modifiers.begin(); + while (result.good() && (it != m_Modifiers.end())) + { + result = (*it)->check(quiet); + it++; + } } - } - if (result.bad()) - { - if (!quiet) + if (result.bad()) { - DCMIOD_ERROR("Invalid code in Code Sequence Macro or its modifiers"); + if (!quiet) + { + DCMIOD_ERROR("Invalid code in Code Sequence Macro or its modifiers"); + } } - } - return result; + return result; } - void CodeWithModifiers::clearData() { - CodeSequenceMacro::clearData(); - DcmIODUtil::freeContainer(m_Modifiers); + CodeSequenceMacro::clearData(); + DcmIODUtil::freeContainer(m_Modifiers); } - int CodeWithModifiers::compare(const IODComponent& rhs) const { - const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs); - if (!r) - return -1; + const CodeWithModifiers* r = OFstatic_cast(const CodeWithModifiers*, &rhs); + if (!r) + return -1; - if (m_Modifiers.size() < r->m_Modifiers.size()) - return -1; - else if (m_Modifiers.size() > r->m_Modifiers.size()) - return 1; + if (m_Modifiers.size() < r->m_Modifiers.size()) + return -1; + else if (m_Modifiers.size() > r->m_Modifiers.size()) + return 1; - int result = IODComponent::compare(*r); - if (result == 0) - { - for (size_t n = 0; (n < m_Modifiers.size()) && (result == 0); n++) + int result = IODComponent::compare(*r); + if (result == 0) { - result = m_Modifiers[n]->compare(*r->m_Modifiers[n]); + for (size_t n = 0; (n < m_Modifiers.size()) && (result == 0); n++) + { + result = m_Modifiers[n]->compare(*r->m_Modifiers[n]); + } } - } - return result; + return result; } - OFString CodeWithModifiers::getName() const { - return "CodeWithModifiers"; + return "CodeWithModifiers"; } - OFCondition CodeWithModifiers::addModifier(const CodeSequenceMacro& modifier) { - OFCondition result = OFconst_cast(CodeSequenceMacro*, &modifier)->check(); - if (result.good()) - { - m_Modifiers.push_back(new CodeSequenceMacro(modifier)); - } - return result; + OFCondition result = OFconst_cast(CodeSequenceMacro*, &modifier)->check(); + if (result.good()) + { + m_Modifiers.push_back(new CodeSequenceMacro(modifier)); + } + return result; } - CodeSequenceMacro* CodeWithModifiers::getModifier(const size_t index) { - if (index + 1 > m_Modifiers.size()) - return NULL; - else - return m_Modifiers[index]; + if (index + 1 > m_Modifiers.size()) + return NULL; + else + return m_Modifiers[index]; } - -OFCondition CodeWithModifiers::read(DcmItem& source, - const OFBool clearOldData) +OFCondition CodeWithModifiers::read(DcmItem& source, const OFBool clearOldData) { - OFCondition result = CodeSequenceMacro::read(source, clearOldData); - if (result.good() && clearOldData) - { - DcmIODUtil::freeContainer(m_Modifiers); - } - if (result.good()) - { - result = DcmIODUtil::readSubSequence(source, m_CodeModifierSeq, m_Modifiers, getRules()->getByTag(m_CodeModifierSeq)); - } - return result; + OFCondition result = CodeSequenceMacro::read(source, clearOldData); + if (result.good() && clearOldData) + { + DcmIODUtil::freeContainer(m_Modifiers); + } + if (result.good()) + { + result = DcmIODUtil::readSubSequence( + source, m_CodeModifierSeq, m_Modifiers, getRules()->getByTag(m_CodeModifierSeq)); + } + return result; } - void CodeWithModifiers::resetRules() { - CodeSequenceMacro::resetRules(); - m_Rules->addRule(new IODRule(m_CodeModifierSeq, m_ModifierVM, m_ModifierType, getName(), DcmIODTypes::IE_UNDEFINED)); + CodeSequenceMacro::resetRules(); + m_Rules->addRule( + new IODRule(m_CodeModifierSeq, m_ModifierVM, m_ModifierType, getName(), DcmIODTypes::IE_UNDEFINED)); } - OFCondition CodeWithModifiers::write(DcmItem& destination) { - OFCondition result; - DcmIODUtil::writeSubSequence(result, m_CodeModifierSeq, m_Modifiers, getData(), getRules()->getByTag(m_CodeModifierSeq)); - if (result.good()) - { - result = CodeSequenceMacro::write(destination); - } - return result; + OFCondition result; + DcmIODUtil::writeSubSequence( + result, m_CodeModifierSeq, m_Modifiers, getData(), getRules()->getByTag(m_CodeModifierSeq)); + if (result.good()) + { + result = CodeSequenceMacro::write(destination); + } + return result; } - CodeWithModifiers::~CodeWithModifiers() { - DcmIODUtil::freeContainer(m_Modifiers); + DcmIODUtil::freeContainer(m_Modifiers); } - OFString CodeSequenceMacro::toString() { - OFString d,m,v; - getCodeValue(v); - getCodeMeaning(m); - getCodingSchemeDesignator(d); - OFStringStream oss; - oss << "(" << d << "," << v << "," << m << ")"; - OFSTRINGSTREAM_GETOFSTRING(oss, msg); - return msg; - + OFString d, m, v; + getCodeValue(v); + getCodeMeaning(m); + getCodingSchemeDesignator(d); + OFStringStream oss; + oss << "(" << d << "," << v << "," << m << ")"; + OFSTRINGSTREAM_GETOFSTRING(oss, msg); + return msg; } - // ---------------------- SeriesAndInstanceReferenceMacro---------------------- const OFString IODSeriesAndInstanceReferenceMacro::m_ComponentName = "SeriesAndInstanceReferenceMacro"; -const OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::m_ComponentName = "SeriesAndInstanceReferenceMacro"; +const OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::m_ComponentName + = "SeriesAndInstanceReferenceMacro"; -IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(OFshared_ptr< DcmItem > data, - OFshared_ptr< IODRules > rules, - IODComponent* parent) : - IODComponent(data, rules, parent), - m_ReferencedSeriesItems() +IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent) + : IODComponent(data, rules, parent) + , m_ReferencedSeriesItems() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - -IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(IODComponent* parent) : - IODComponent(parent), - m_ReferencedSeriesItems() +IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(IODComponent* parent) + : IODComponent(parent) + , m_ReferencedSeriesItems() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODSeriesAndInstanceReferenceMacro::getName() const { - return m_ComponentName; + return m_ComponentName; } - -OFCondition IODSeriesAndInstanceReferenceMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODSeriesAndInstanceReferenceMacro::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - DcmIODUtil::readSubSequence >(source, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); - return EC_Normal; + DcmIODUtil::readSubSequence >( + source, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + return EC_Normal; } - OFCondition IODSeriesAndInstanceReferenceMacro::write(DcmItem& destination) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - DcmIODUtil::writeSubSequence >(result, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, destination, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + DcmIODUtil::writeSubSequence >(result, + DCM_ReferencedSeriesSequence, + m_ReferencedSeriesItems, + destination, + m_Rules->getByTag(DCM_ReferencedSeriesSequence)); - return result; + return result; } - void IODSeriesAndInstanceReferenceMacro::clearData() { - DcmIODUtil::freeContainer(m_ReferencedSeriesItems); + DcmIODUtil::freeContainer(m_ReferencedSeriesItems); } - void IODSeriesAndInstanceReferenceMacro::resetRules() { - m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - -OFVector< IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* >& IODSeriesAndInstanceReferenceMacro::getReferencedSeriesItems() +OFVector& +IODSeriesAndInstanceReferenceMacro::getReferencedSeriesItems() { - return m_ReferencedSeriesItems; + return m_ReferencedSeriesItems; } - IODSeriesAndInstanceReferenceMacro::~IODSeriesAndInstanceReferenceMacro() { - DcmIODUtil::freeContainer(m_ReferencedSeriesItems); + DcmIODUtil::freeContainer(m_ReferencedSeriesItems); } - -IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, - IODComponent* parent) -: IODComponent(item, rules, parent), - m_ReferencedInstanceSequence() +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent) + : IODComponent(item, rules, parent) + , m_ReferencedInstanceSequence() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(IODComponent* parent) -: IODComponent(parent), - m_ReferencedInstanceSequence() + : IODComponent(parent) + , m_ReferencedInstanceSequence() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::~ReferencedSeriesItem() { - clearData(); + clearData(); } - OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getName() const { - return m_ComponentName; + return m_ComponentName; } - void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::clearData() { - DcmIODUtil::freeContainer(m_ReferencedInstanceSequence); - IODComponent::clearData(); + DcmIODUtil::freeContainer(m_ReferencedInstanceSequence); + IODComponent::clearData(); } - - -OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - IODComponent::read(source, clearOldData); - DcmIODUtil::readSubSequence(source, DCM_ReferencedInstanceSequence, m_ReferencedInstanceSequence, m_Rules->getByTag(DCM_ReferencedInstanceSequence)); - return EC_Normal; + IODComponent::read(source, clearOldData); + DcmIODUtil::readSubSequence(source, + DCM_ReferencedInstanceSequence, + m_ReferencedInstanceSequence, + m_Rules->getByTag(DCM_ReferencedInstanceSequence)); + return EC_Normal; } - OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::write(DcmItem& destination) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - DcmIODUtil::writeSubSequence >(result, DCM_ReferencedInstanceSequence, m_ReferencedInstanceSequence, *m_Item, m_Rules->getByTag(DCM_ReferencedInstanceSequence)); - result = IODComponent::write(destination); + DcmIODUtil::writeSubSequence >( + result, + DCM_ReferencedInstanceSequence, + m_ReferencedInstanceSequence, + *m_Item, + m_Rules->getByTag(DCM_ReferencedInstanceSequence)); + result = IODComponent::write(destination); - return result; + return result; } - void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::resetRules() { - // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level - m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - -OFVector< SOPInstanceReferenceMacro* >& IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getReferencedInstanceItems() +OFVector& +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getReferencedInstanceItems() { - return m_ReferencedInstanceSequence; + return m_ReferencedInstanceSequence; } - -OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getSeriesInstanceUID(OFString& value, - const long signed int pos) const +OFCondition +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getSeriesInstanceUID(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); } - OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::setSeriesInstanceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); + return result; } -OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::addReference( - const OFString& sopClassUID, - const OFString& sopInstanceUID) +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::addReference(const OFString& sopClassUID, + const OFString& sopInstanceUID) { - OFVector::iterator instance = m_ReferencedInstanceSequence.begin(); - while (instance != m_ReferencedInstanceSequence.end()) - { - OFString c,i; - (*instance)->getReferencedSOPClassUID(c); - (*instance)->getReferencedSOPInstanceUID(i); - if ( i == sopInstanceUID) + OFVector::iterator instance = m_ReferencedInstanceSequence.begin(); + while (instance != m_ReferencedInstanceSequence.end()) { - DCMIOD_DEBUG("Skipping doubled instance reference when adding to Series and Instance Reference Macro"); - return EC_Normal; + OFString c, i; + (*instance)->getReferencedSOPClassUID(c); + (*instance)->getReferencedSOPInstanceUID(i); + if (i == sopInstanceUID) + { + DCMIOD_DEBUG("Skipping doubled instance reference when adding to Series and Instance Reference Macro"); + return EC_Normal; + } + else + { + instance++; + } + } + // We get here in case that we do not have this reference, add new one + SOPInstanceReferenceMacro* macro = new SOPInstanceReferenceMacro(); + if (!macro) + { + return EC_MemoryExhausted; + } + OFCondition result = macro->setReferencedSOPClassUID(sopClassUID); + if (result.good()) + result = macro->setReferencedSOPInstanceUID(sopInstanceUID); + if (result.good()) + { + m_ReferencedInstanceSequence.push_back(macro); } else { - instance++; + delete macro; + result = IOD_EC_InvalidElementValue; } - } - // We get here in case that we do not have this reference, add new one - SOPInstanceReferenceMacro* macro = new SOPInstanceReferenceMacro(); - if (!macro) - { - return EC_MemoryExhausted; - } - OFCondition result = macro->setReferencedSOPClassUID(sopClassUID); - if (result.good()) result = macro->setReferencedSOPInstanceUID(sopInstanceUID); - if (result.good()) - { - m_ReferencedInstanceSequence.push_back(macro); - } - else - { - delete macro; - result = IOD_EC_InvalidElementValue; - } - return result; + return result; } - // ---------------------- SOPInstanceReferenceMacro ---------------------- - -SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, +SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(OFshared_ptr item, + OFshared_ptr rules, IODComponent* parent) -: IODComponent(item, rules, parent) + : IODComponent(item, rules, parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(IODComponent* parent) -: IODComponent(parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - SOPInstanceReferenceMacro::~SOPInstanceReferenceMacro() { - // nothing to do + // nothing to do } - OFString SOPInstanceReferenceMacro::getName() const { - return "SOPInstanceReferenceMacro"; + return "SOPInstanceReferenceMacro"; } - void SOPInstanceReferenceMacro::resetRules() { - // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level - m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); } - // -- get dicom attributes -- -OFCondition SOPInstanceReferenceMacro::getReferencedSOPClassUID(OFString &value, - const signed long pos) +OFCondition SOPInstanceReferenceMacro::getReferencedSOPClassUID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *m_Item, value, pos); } -OFCondition SOPInstanceReferenceMacro::getReferencedSOPInstanceUID(OFString &value, - const signed long pos) +OFCondition SOPInstanceReferenceMacro::getReferencedSOPInstanceUID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *m_Item, value, pos); } // -- set dicom attributes -- -OFCondition SOPInstanceReferenceMacro::setReferencedSOPClassUID(const OFString& value, - const OFBool checkValue) +OFCondition SOPInstanceReferenceMacro::setReferencedSOPClassUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); + return result; } - -OFCondition SOPInstanceReferenceMacro::setReferencedSOPInstanceUID(const OFString& value, - const OFBool checkValue) +OFCondition SOPInstanceReferenceMacro::setReferencedSOPInstanceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); + return result; } - // ---------------------- ImageSOPInstanceReferenceMacro ---------------------- - ImageSOPInstanceReferenceMacro::ImageSOPInstanceReferenceMacro() - : ReferencedFrameNumber(DCM_ReferencedFrameNumber), - ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) + : ReferencedFrameNumber(DCM_ReferencedFrameNumber) + , ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) { - } - OFCondition ImageSOPInstanceReferenceMacro::create(const OFString& sopClassUID, const OFString& sopInstanceUID, ImageSOPInstanceReferenceMacro*& result) { - result = new ImageSOPInstanceReferenceMacro(); - if (!result) - return EC_MemoryExhausted; + result = new ImageSOPInstanceReferenceMacro(); + if (!result) + return EC_MemoryExhausted; - OFCondition cond = result->setReferencedSOPClassUID(sopClassUID); - if (cond.good()) - { - cond = result->setReferencedSOPInstanceUID(sopInstanceUID); - } - if (cond.bad()) - { - delete result; - result = NULL; - } - return cond; + OFCondition cond = result->setReferencedSOPClassUID(sopClassUID); + if (cond.good()) + { + cond = result->setReferencedSOPInstanceUID(sopInstanceUID); + } + if (cond.bad()) + { + delete result; + result = NULL; + } + return cond; } - OFCondition ImageSOPInstanceReferenceMacro::create(const OFString& sopClassUID, const OFString& sopInstanceUID, - const OFVector< Uint16 >& refFramesOrSegments, + const OFVector& refFramesOrSegments, ImageSOPInstanceReferenceMacro*& result) { - OFCondition cond = create(sopClassUID, sopInstanceUID, result); - if (cond.good()) - { - if (!refFramesOrSegments.empty()) + OFCondition cond = create(sopClassUID, sopInstanceUID, result); + if (cond.good()) { - if (sopClassUID == UID_SegmentationStorage) - { - cond = result->setReferencedSegmentNumber(refFramesOrSegments); - } - else - { - cond = result->setReferencedFrameNumber(refFramesOrSegments); - } - } - if (cond.bad()) - { - delete result; - result = NULL; + if (!refFramesOrSegments.empty()) + { + if (sopClassUID == UID_SegmentationStorage) + { + cond = result->setReferencedSegmentNumber(refFramesOrSegments); + } + else + { + cond = result->setReferencedFrameNumber(refFramesOrSegments); + } + } + if (cond.bad()) + { + delete result; + result = NULL; + } } - } - return cond; + return cond; } - ImageSOPInstanceReferenceMacro::~ImageSOPInstanceReferenceMacro() { } int ImageSOPInstanceReferenceMacro::compare(const IODComponent& rhs) const { - const ImageSOPInstanceReferenceMacro *macro = OFstatic_cast(const ImageSOPInstanceReferenceMacro*, &rhs); - if (macro == NULL) return -1; - int result = ReferencedFrameNumber.compare(macro->ReferencedFrameNumber); - if (result == 0) ReferencedSegmentNumber.compare(macro->ReferencedSegmentNumber); - if (result == 0) return SOPInstanceReferenceMacro::compare(rhs); - return result; + const ImageSOPInstanceReferenceMacro* macro = OFstatic_cast(const ImageSOPInstanceReferenceMacro*, &rhs); + if (macro == NULL) + return -1; + int result = ReferencedFrameNumber.compare(macro->ReferencedFrameNumber); + if (result == 0) + ReferencedSegmentNumber.compare(macro->ReferencedSegmentNumber); + if (result == 0) + return SOPInstanceReferenceMacro::compare(rhs); + return result; } void ImageSOPInstanceReferenceMacro::clear() { - SOPInstanceReferenceMacro::clearData(); - ReferencedFrameNumber.clear(); - ReferencedSegmentNumber.clear(); + SOPInstanceReferenceMacro::clearData(); + ReferencedFrameNumber.clear(); + ReferencedSegmentNumber.clear(); } - -OFCondition ImageSOPInstanceReferenceMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition ImageSOPInstanceReferenceMacro::read(DcmItem& source, const OFBool clearOldData) { - /* re-initialize object */ - if (clearOldData) - clear(); + /* re-initialize object */ + if (clearOldData) + clear(); - OFCondition result = SOPInstanceReferenceMacro::read(source, clearOldData); + OFCondition result = SOPInstanceReferenceMacro::read(source, clearOldData); - DcmIODUtil::getAndCheckElementFromDataset(source, ReferencedFrameNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); - DcmIODUtil::getAndCheckElementFromDataset(source, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + source, ReferencedFrameNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + DcmIODUtil::getAndCheckElementFromDataset( + source, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); - return result; + return result; } - OFCondition ImageSOPInstanceReferenceMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; - /* copy all elements to dataset */ - DcmIODUtil::copyElementToDataset(result, item, ReferencedFrameNumber, "1-n" /* VM */, "1C" /* Type */, "ImageSOPInstanceReferenceMacro"); - DcmIODUtil::copyElementToDataset(result, item, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + OFCondition result = EC_Normal; + /* copy all elements to dataset */ + DcmIODUtil::copyElementToDataset( + result, item, ReferencedFrameNumber, "1-n" /* VM */, "1C" /* Type */, "ImageSOPInstanceReferenceMacro"); + DcmIODUtil::copyElementToDataset( + result, item, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); - if ( result.good() ) - result = SOPInstanceReferenceMacro::write(item); + if (result.good()) + result = SOPInstanceReferenceMacro::write(item); - return result; + return result; } // -- get dicom attributes -- -OFCondition ImageSOPInstanceReferenceMacro::getReferencedFrameNumber(OFVector &values) +OFCondition ImageSOPInstanceReferenceMacro::getReferencedFrameNumber(OFVector& values) { - // cast away const since underlying dcmdata routine is not const... - DcmIntegerString *is = OFconst_cast(DcmIntegerString*, &ReferencedFrameNumber); - for (size_t n = 0; n < is->getNumberOfValues(); n++) - { - Sint32 sint = 0; - is->getSint32(sint, OFstatic_cast(unsigned long, n)); - if (sint < 0) + // cast away const since underlying dcmdata routine is not const... + DcmIntegerString* is = OFconst_cast(DcmIntegerString*, &ReferencedFrameNumber); + for (size_t n = 0; n < is->getNumberOfValues(); n++) { - DCMIOD_WARN("Invalid Referenced Frame Number in Image SOP Instance Reference Macro: " << sint); - return EC_CorruptedData; + Sint32 sint = 0; + is->getSint32(sint, OFstatic_cast(unsigned long, n)); + if (sint < 0) + { + DCMIOD_WARN("Invalid Referenced Frame Number in Image SOP Instance Reference Macro: " << sint); + return EC_CorruptedData; + } + values.push_back(OFstatic_cast(Uint16, sint)); } - values.push_back(OFstatic_cast(Uint16, sint)); - } - return EC_Normal; + return EC_Normal; } - -OFCondition ImageSOPInstanceReferenceMacro::getReferencedSegmentNumber(OFVector &values) +OFCondition ImageSOPInstanceReferenceMacro::getReferencedSegmentNumber(OFVector& values) { - // cast away const since underlying dcmdata routine is not const... - DcmUnsignedShort *us = OFconst_cast(DcmUnsignedShort*, &ReferencedSegmentNumber); - return DcmIODUtil::getUint16ValuesFromElement(*us, values); + // cast away const since underlying dcmdata routine is not const... + DcmUnsignedShort* us = OFconst_cast(DcmUnsignedShort*, &ReferencedSegmentNumber); + return DcmIODUtil::getUint16ValuesFromElement(*us, values); } // -- set dicom attributes -- - OFCondition ImageSOPInstanceReferenceMacro::setReferencedFrameNumber(const OFVector& values, const OFBool checkValue) { - return DcmIODUtil::setUint16ValuesOnElement(ReferencedFrameNumber, values, "1-n", checkValue); + return DcmIODUtil::setUint16ValuesOnElement(ReferencedFrameNumber, values, "1-n", checkValue); } - -OFCondition ImageSOPInstanceReferenceMacro::addReferencedFrameNumber(const Uint16& value, - const OFBool checkValue) +OFCondition ImageSOPInstanceReferenceMacro::addReferencedFrameNumber(const Uint16& value, const OFBool checkValue) { - (void)checkValue; - OFString val; - ReferencedFrameNumber.getOFStringArray(val); - if (ReferencedFrameNumber.getNumberOfValues() > 0) - { - val += "\\"; - } - char buf[10]; - sprintf(buf, "%u", value); - val += buf; - return ReferencedFrameNumber.putOFStringArray(val); + (void)checkValue; + OFString val; + ReferencedFrameNumber.getOFStringArray(val); + if (ReferencedFrameNumber.getNumberOfValues() > 0) + { + val += "\\"; + } + char buf[10]; + sprintf(buf, "%u", value); + val += buf; + return ReferencedFrameNumber.putOFStringArray(val); } - - OFCondition ImageSOPInstanceReferenceMacro::setReferencedSegmentNumber(const OFVector& values, const OFBool checkValue) { - return DcmIODUtil::setUint16ValuesOnElement(ReferencedSegmentNumber, values, "1-n", checkValue); + return DcmIODUtil::setUint16ValuesOnElement(ReferencedSegmentNumber, values, "1-n", checkValue); } - -OFCondition ImageSOPInstanceReferenceMacro::addReferencedSegmentNumber(const Uint16& value, - const OFBool checkValue) +OFCondition ImageSOPInstanceReferenceMacro::addReferencedSegmentNumber(const Uint16& value, const OFBool checkValue) { - (void)checkValue; - const unsigned long count = ReferencedSegmentNumber.getNumberOfValues(); - return ReferencedSegmentNumber.putUint16(value, count /* starts with 0, so add new value at the end */); - + (void)checkValue; + const unsigned long count = ReferencedSegmentNumber.getNumberOfValues(); + return ReferencedSegmentNumber.putUint16(value, count /* starts with 0, so add new value at the end */); } - // ---------------------- GeneralAnatomyMacro ---------------------- - -GeneralAnatomyMacro::GeneralAnatomyMacro(const OFString& type) : - m_Type(type), - m_AnatomicRegion(), - m_AnatomicRegionModifier(), - m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */, "1", DCM_PrimaryAnatomicStructureModifierSequence) +GeneralAnatomyMacro::GeneralAnatomyMacro(const OFString& type) + : m_Type(type) + , m_AnatomicRegion() + , m_AnatomicRegionModifier() + , m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */, + "1", + DCM_PrimaryAnatomicStructureModifierSequence) { - m_Type = type; + m_Type = type; } - GeneralAnatomyMacro::GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs) -: m_Type(rhs.m_Type), - m_AnatomicRegion(), - m_AnatomicRegionModifier(), - m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */, "1", DCM_PrimaryAnatomicStructureModifierSequence) + : m_Type(rhs.m_Type) + , m_AnatomicRegion() + , m_AnatomicRegionModifier() + , m_PrimaryAnatomicStructure("3" /* Modifier in Primary Anatomic Structure is always optional */, + "1", + DCM_PrimaryAnatomicStructureModifierSequence) { - *this = rhs; + *this = rhs; } - GeneralAnatomyMacro& GeneralAnatomyMacro::operator=(const GeneralAnatomyMacro& rhs) { - if (this != &rhs) - { - clearData(); - m_Type = rhs.m_Type; - m_AnatomicRegion = rhs.m_AnatomicRegion; - m_PrimaryAnatomicStructure = rhs.m_PrimaryAnatomicStructure; - - OFVector::const_iterator it = rhs.m_AnatomicRegionModifier.begin(); - while ( it != rhs.m_AnatomicRegionModifier.end() ) + if (this != &rhs) { - m_AnatomicRegionModifier.push_back( new CodeSequenceMacro(**it) ); - it++; + clearData(); + m_Type = rhs.m_Type; + m_AnatomicRegion = rhs.m_AnatomicRegion; + m_PrimaryAnatomicStructure = rhs.m_PrimaryAnatomicStructure; + + OFVector::const_iterator it = rhs.m_AnatomicRegionModifier.begin(); + while (it != rhs.m_AnatomicRegionModifier.end()) + { + m_AnatomicRegionModifier.push_back(new CodeSequenceMacro(**it)); + it++; + } } - } - return *this; + return *this; } - GeneralAnatomyMacro::~GeneralAnatomyMacro() { - clearData(); + clearData(); } - void GeneralAnatomyMacro::clearData() { - // m_Type stays the same - m_AnatomicRegion.clearData(); - DcmIODUtil::freeContainer(m_AnatomicRegionModifier); - m_PrimaryAnatomicStructure.clearData(); + // m_Type stays the same + m_AnatomicRegion.clearData(); + DcmIODUtil::freeContainer(m_AnatomicRegionModifier); + m_PrimaryAnatomicStructure.clearData(); } - OFCondition GeneralAnatomyMacro::check(const OFBool quiet) { - OFCondition result = m_AnatomicRegion.check(quiet); - if (result.bad()) - return result; + OFCondition result = m_AnatomicRegion.check(quiet); + if (result.bad()) + return result; - OFVector::iterator it = m_AnatomicRegionModifier.begin(); - while (it != m_AnatomicRegionModifier.begin()) - { - result = (*it)->check(quiet); - if (result.bad()) return result; - it++; - } - // Primary Anatomic Structure is optional (type 3), so only check if - // user intended to fill in something. - if (!m_PrimaryAnatomicStructure.empty()) - { - result = m_PrimaryAnatomicStructure.check(quiet); - } - return result; + OFVector::iterator it = m_AnatomicRegionModifier.begin(); + while (it != m_AnatomicRegionModifier.begin()) + { + result = (*it)->check(quiet); + if (result.bad()) + return result; + it++; + } + // Primary Anatomic Structure is optional (type 3), so only check if + // user intended to fill in something. + if (!m_PrimaryAnatomicStructure.empty()) + { + result = m_PrimaryAnatomicStructure.check(quiet); + } + return result; } - CodeSequenceMacro& GeneralAnatomyMacro::getAnatomicRegion() { - return m_AnatomicRegion; + return m_AnatomicRegion; } - OFVector& GeneralAnatomyMacro::getAnatomicRegionModifier() { - return m_AnatomicRegionModifier; + return m_AnatomicRegionModifier; } - PrimaryAnatomicStructureMacro& GeneralAnatomyMacro::getPrimaryAnatomicStructure() { - return m_PrimaryAnatomicStructure; + return m_PrimaryAnatomicStructure; } - // Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item -OFCondition GeneralAnatomyMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition GeneralAnatomyMacro::read(DcmItem& source, const OFBool clearOldData) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - /* re-initialize object */ - if (clearOldData) - clearData(); + /* re-initialize object */ + if (clearOldData) + clearData(); - /* read Anatomic Region Sequence item into Code Sequence Macro */ - DcmIODUtil::readSingleItem(source, DCM_AnatomicRegionSequence, m_AnatomicRegion, m_Type, "GeneralAnatomyMacro"); + /* read Anatomic Region Sequence item into Code Sequence Macro */ + DcmIODUtil::readSingleItem( + source, DCM_AnatomicRegionSequence, m_AnatomicRegion, m_Type, "GeneralAnatomyMacro"); - /* read Primary Anatomic Structure Macro (main level, i.e.\ original item) */ - DcmIODUtil::readSingleItem(source, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, "3", "GeneralAnatomyMacro"); + /* read Primary Anatomic Structure Macro (main level, i.e.\ original item) */ + DcmIODUtil::readSingleItem( + source, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, "3", "GeneralAnatomyMacro"); - /* Get the single item from Anatomic Region Sequence and read modifier if found */ - DcmItem* localItem = NULL; - if ( source.findAndGetSequenceItem(DCM_AnatomicRegionSequence, localItem).bad() ) - { - return result; - } + /* Get the single item from Anatomic Region Sequence and read modifier if found */ + DcmItem* localItem = NULL; + if (source.findAndGetSequenceItem(DCM_AnatomicRegionSequence, localItem).bad()) + { + return result; + } - /* read Anatomic Region Modifier Sequence from */ - DcmIODUtil::readSubSequence > - ( *localItem, /* item of Anatomic Region Sequence */ - DCM_AnatomicRegionModifierSequence, - m_AnatomicRegionModifier, - "1-n", - "3", - "GeneralAnatomyMacro" ); + /* read Anatomic Region Modifier Sequence from */ + DcmIODUtil::readSubSequence >(*localItem, /* item of Anatomic Region Sequence */ + DCM_AnatomicRegionModifierSequence, + m_AnatomicRegionModifier, + "1-n", + "3", + "GeneralAnatomyMacro"); - return result; + return result; } - /// Write Anatomic Region Sequence from given item OFCondition GeneralAnatomyMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - /* delete old data */ - item.findAndDeleteElement(DCM_AnatomicRegionSequence); - item.findAndDeleteElement(DCM_PrimaryAnatomicStructureSequence); + /* delete old data */ + item.findAndDeleteElement(DCM_AnatomicRegionSequence); + item.findAndDeleteElement(DCM_PrimaryAnatomicStructureSequence); - /* Write sub structures */ - DcmIODUtil::writeSingleItem(result, DCM_AnatomicRegionSequence, m_AnatomicRegion, item, m_Type, "GeneralAnatomyMacro"); - if (result.good()) - { - DcmItem* seqItem = NULL; - result = item.findAndGetSequenceItem(DCM_AnatomicRegionSequence, seqItem, 0); + /* Write sub structures */ + DcmIODUtil::writeSingleItem( + result, DCM_AnatomicRegionSequence, m_AnatomicRegion, item, m_Type, "GeneralAnatomyMacro"); if (result.good()) { - DcmIODUtil::writeSubSequence > - ( result, - DCM_AnatomicRegionModifierSequence, - m_AnatomicRegionModifier, - *seqItem, - "1-n", - "3", - "GeneralAnatomyMacro"); + DcmItem* seqItem = NULL; + result = item.findAndGetSequenceItem(DCM_AnatomicRegionSequence, seqItem, 0); + if (result.good()) + { + DcmIODUtil::writeSubSequence >(result, + DCM_AnatomicRegionModifierSequence, + m_AnatomicRegionModifier, + *seqItem, + "1-n", + "3", + "GeneralAnatomyMacro"); + } } - } - DcmIODUtil::writeSingleItem(result, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, item, "3", "GeneralAnatomyMacro"); - return result; + DcmIODUtil::writeSingleItem( + result, DCM_PrimaryAnatomicStructureSequence, m_PrimaryAnatomicStructure, item, "3", "GeneralAnatomyMacro"); + return result; } - int GeneralAnatomyMacro::compare(const GeneralAnatomyMacro& rhs) const { - int result = m_AnatomicRegion.compare(rhs.m_AnatomicRegion); - if (result == 0) - { - if (m_AnatomicRegionModifier.size() > rhs.m_AnatomicRegionModifier.size()) + int result = m_AnatomicRegion.compare(rhs.m_AnatomicRegion); + if (result == 0) { - return 1; - } - else if (m_AnatomicRegionModifier.size() < rhs.m_AnatomicRegionModifier.size()) - { - return -1; - } + if (m_AnatomicRegionModifier.size() > rhs.m_AnatomicRegionModifier.size()) + { + return 1; + } + else if (m_AnatomicRegionModifier.size() < rhs.m_AnatomicRegionModifier.size()) + { + return -1; + } - for (size_t m = 0; m < m_AnatomicRegionModifier.size(); m++) - { - rhs.m_AnatomicRegionModifier[m]; - result = m_AnatomicRegionModifier[m]->compare( *(rhs.m_AnatomicRegionModifier[m]) ); - if (result != 0) - { - return result; - } + for (size_t m = 0; m < m_AnatomicRegionModifier.size(); m++) + { + result = m_AnatomicRegionModifier[m]->compare(*(rhs.m_AnatomicRegionModifier[m])); + if (result != 0) + { + return result; + } + } + result = m_PrimaryAnatomicStructure.compare(rhs.m_PrimaryAnatomicStructure); } - result = m_PrimaryAnatomicStructure.compare(rhs.m_PrimaryAnatomicStructure); - } - return result; + return result; } - // ---------------------- AlgorithmIdentificationMacro ---------------------- - -AlgorithmIdentificationMacro::AlgorithmIdentificationMacro() : - m_AlgorithmFamilyCode(), - m_AlgorithmNameCode(), - m_AlgorithmName(DCM_AlgorithmName), - m_AlgorithmVersion(DCM_AlgorithmVersion), - m_AlgorithmParameters(DCM_AlgorithmParameters), - m_AlgorithmSource(DCM_AlgorithmSource) +AlgorithmIdentificationMacro::AlgorithmIdentificationMacro() + : m_AlgorithmFamilyCode() + , m_AlgorithmNameCode() + , m_AlgorithmName(DCM_AlgorithmName) + , m_AlgorithmVersion(DCM_AlgorithmVersion) + , m_AlgorithmParameters(DCM_AlgorithmParameters) + , m_AlgorithmSource(DCM_AlgorithmSource) { - } // AlgorithmIdentificationMacro::~AlgorithmIdentificationMacro() { - clearData(); + clearData(); } - void AlgorithmIdentificationMacro::clearData() { - m_AlgorithmFamilyCode.clearData(); - m_AlgorithmNameCode.clearData(); - m_AlgorithmName.clear(); - m_AlgorithmVersion.clear(); - m_AlgorithmParameters.clear(); - m_AlgorithmSource.clear(); + m_AlgorithmFamilyCode.clearData(); + m_AlgorithmNameCode.clearData(); + m_AlgorithmName.clear(); + m_AlgorithmVersion.clear(); + m_AlgorithmParameters.clear(); + m_AlgorithmSource.clear(); } - OFCondition AlgorithmIdentificationMacro::check(const OFBool quiet) { - OFCondition result; - result = m_AlgorithmFamilyCode.check(quiet); - if ( result.good() ) - { - if ( m_AlgorithmName.isEmpty() || m_AlgorithmVersion.isEmpty() ) + OFCondition result; + result = m_AlgorithmFamilyCode.check(quiet); + if (result.good()) { - result = EC_MissingValue; + if (m_AlgorithmName.isEmpty() || m_AlgorithmVersion.isEmpty()) + { + result = EC_MissingValue; + } } - } - return result; + return result; } - - CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmFamilyCode() { - return m_AlgorithmFamilyCode; + return m_AlgorithmFamilyCode; } - CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmNameCode() { - return m_AlgorithmNameCode; + return m_AlgorithmNameCode; } - -OFCondition AlgorithmIdentificationMacro::getAlgorithmName(OFString& value, - const signed long pos) +OFCondition AlgorithmIdentificationMacro::getAlgorithmName(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_AlgorithmName, value, pos); + return DcmIODUtil::getStringValueFromElement(m_AlgorithmName, value, pos); } - -OFCondition AlgorithmIdentificationMacro::getAlgorithmVersion(OFString& value, - const signed long pos) +OFCondition AlgorithmIdentificationMacro::getAlgorithmVersion(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_AlgorithmVersion, value, pos); + return DcmIODUtil::getStringValueFromElement(m_AlgorithmVersion, value, pos); } - -OFCondition AlgorithmIdentificationMacro::getAlgorithmParameters(OFString& value, - const signed long pos) +OFCondition AlgorithmIdentificationMacro::getAlgorithmParameters(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_AlgorithmParameters, value, pos); + return DcmIODUtil::getStringValueFromElement(m_AlgorithmParameters, value, pos); } - -OFCondition AlgorithmIdentificationMacro::getAlgorithmSource(OFString& value, - const signed long pos) +OFCondition AlgorithmIdentificationMacro::getAlgorithmSource(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_AlgorithmSource, value, pos); + return DcmIODUtil::getStringValueFromElement(m_AlgorithmSource, value, pos); } - -OFCondition AlgorithmIdentificationMacro::setAlgorithmName(const OFString& value, - const OFBool checkValue) +OFCondition AlgorithmIdentificationMacro::setAlgorithmName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_AlgorithmName.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmName.putOFStringArray(value); + return result; } - -OFCondition AlgorithmIdentificationMacro::setAlgorithmVersion(const OFString& value, - const OFBool checkValue) +OFCondition AlgorithmIdentificationMacro::setAlgorithmVersion(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_AlgorithmVersion.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmVersion.putOFStringArray(value); + return result; } - -OFCondition AlgorithmIdentificationMacro::setAlgorithmParameters(const OFString& value, - const OFBool checkValue) +OFCondition AlgorithmIdentificationMacro::setAlgorithmParameters(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_AlgorithmParameters.putOFStringArray(value); + (void)checkValue; + return m_AlgorithmParameters.putOFStringArray(value); } - -OFCondition AlgorithmIdentificationMacro::setAlgorithmSource(const OFString& value, - const OFBool checkValue) +OFCondition AlgorithmIdentificationMacro::setAlgorithmSource(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_AlgorithmSource.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmSource.putOFStringArray(value); + return result; } - /// Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item -OFCondition AlgorithmIdentificationMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition AlgorithmIdentificationMacro::read(DcmItem& source, const OFBool clearOldData) { - OFCondition result; + OFCondition result; - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - DcmIODUtil::readSingleItem - ( - source, - DCM_AlgorithmFamilyCodeSequence, - m_AlgorithmFamilyCode, - "1", - "AlgorithmIdentificationMacro" - ); + DcmIODUtil::readSingleItem( + source, DCM_AlgorithmFamilyCodeSequence, m_AlgorithmFamilyCode, "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::readSingleItem - ( - source, - DCM_AlgorithmNameCodeSequence, - m_AlgorithmNameCode, - "3", - "AlgorithmIdentificationMacro"); + DcmIODUtil::readSingleItem( + source, DCM_AlgorithmNameCodeSequence, m_AlgorithmNameCode, "3", "AlgorithmIdentificationMacro"); - DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); - DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); - return result; + return result; } - OFCondition AlgorithmIdentificationMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - // write to item - DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); - DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); + // write to item + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); - DcmIODUtil::writeSingleItem - ( result, - DCM_AlgorithmFamilyCodeSequence, - m_AlgorithmFamilyCode, - item, - "1", - "AlgorithmIdentificationMacro" - ); + DcmIODUtil::writeSingleItem( + result, DCM_AlgorithmFamilyCodeSequence, m_AlgorithmFamilyCode, item, "1", "AlgorithmIdentificationMacro"); - DcmIODUtil::writeSingleItem - ( result, - DCM_AlgorithmNameCodeSequence, - m_AlgorithmNameCode, - item, - "3", - "AlgorithmIdentificationMacro" - ); + DcmIODUtil::writeSingleItem( + result, DCM_AlgorithmNameCodeSequence, m_AlgorithmNameCode, item, "3", "AlgorithmIdentificationMacro"); - return result; + return result; } - // ---------------------- ContentIdentificationMacro ---------------------- -ContentIdentificationMacro::ContentIdentificationMacro() : - m_InstanceNumber(DCM_InstanceNumber), - m_ContentLabel(DCM_ContentLabel), - m_ContentDescription(DCM_ContentDescription), - m_AlternateContentDescription(), - m_ContentCreatorName(DCM_ContentCreatorName), - m_ContentCreatorIdentificationCode(), - m_IODRules() +ContentIdentificationMacro::ContentIdentificationMacro() + : m_InstanceNumber(DCM_InstanceNumber) + , m_ContentLabel(DCM_ContentLabel) + , m_ContentDescription(DCM_ContentDescription) + , m_AlternateContentDescription() + , m_ContentCreatorName(DCM_ContentCreatorName) + , m_ContentCreatorIdentificationCode() + , m_IODRules() { - resetRules(); + resetRules(); } - ContentIdentificationMacro::ContentIdentificationMacro(const OFString& instanceNumber, const OFString& contentLabel, const OFString& contentDescription, - const OFString& contentCreatorName) : - m_InstanceNumber(DCM_InstanceNumber), - m_ContentLabel(DCM_ContentLabel), - m_ContentDescription(DCM_ContentDescription), - m_AlternateContentDescription(), - m_ContentCreatorName(DCM_ContentCreatorName), - m_ContentCreatorIdentificationCode(), - m_IODRules() + const OFString& contentCreatorName) + : m_InstanceNumber(DCM_InstanceNumber) + , m_ContentLabel(DCM_ContentLabel) + , m_ContentDescription(DCM_ContentDescription) + , m_AlternateContentDescription() + , m_ContentCreatorName(DCM_ContentCreatorName) + , m_ContentCreatorIdentificationCode() + , m_IODRules() { - resetRules(); - setInstanceNumber(instanceNumber); - setContentLabel(contentLabel); - setContentDescription(contentDescription); - setContentCreatorName(contentCreatorName); + resetRules(); + setInstanceNumber(instanceNumber); + setContentLabel(contentLabel); + setContentDescription(contentDescription); + setContentCreatorName(contentCreatorName); } - void ContentIdentificationMacro::resetRules() { - m_IODRules.addRule(new IODRule(DCM_InstanceNumber, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_IODRules.addRule(new IODRule(DCM_ContentLabel, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_IODRules.addRule(new IODRule(DCM_ContentDescription, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_IODRules.addRule(new IODRule(DCM_ContentCreatorName, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_IODRules.addRule(new IODRule(DCM_AlternateContentDescriptionSequence, "1-n", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_IODRules.addRule(new IODRule(DCM_ContentCreatorIdentificationCodeSequence, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_InstanceNumber, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentLabel, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentDescription, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentCreatorName, "1", "2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule( + new IODRule(DCM_AlternateContentDescriptionSequence, "1-n", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule( + new IODRule(DCM_ContentCreatorIdentificationCodeSequence, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - OFString ContentIdentificationMacro::getName() const { - return "ContentIdentificationMacro"; + return "ContentIdentificationMacro"; } - IODRules& ContentIdentificationMacro::getIODRules() { - return m_IODRules; + return m_IODRules; } - -ContentIdentificationMacro::ContentIdentificationMacro(const ContentIdentificationMacro& rhs) : - m_InstanceNumber(DCM_InstanceNumber), - m_ContentLabel(DCM_ContentLabel), - m_ContentDescription(DCM_ContentDescription), - m_AlternateContentDescription(), - m_ContentCreatorName(DCM_ContentCreatorName), - m_ContentCreatorIdentificationCode(), - m_IODRules() +ContentIdentificationMacro::ContentIdentificationMacro(const ContentIdentificationMacro& rhs) + : m_InstanceNumber(DCM_InstanceNumber) + , m_ContentLabel(DCM_ContentLabel) + , m_ContentDescription(DCM_ContentDescription) + , m_AlternateContentDescription() + , m_ContentCreatorName(DCM_ContentCreatorName) + , m_ContentCreatorIdentificationCode() + , m_IODRules() { - if (&rhs != this) - { - resetRules(); - m_InstanceNumber = rhs.m_InstanceNumber; - m_ContentLabel = rhs.m_ContentLabel; - m_ContentDescription = rhs.m_ContentDescription; - m_ContentCreatorName = rhs.m_ContentCreatorName; - m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; - /* perform deep vector copy */ - OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); - while (it != rhs.m_AlternateContentDescription.end()) + if (&rhs != this) { - m_AlternateContentDescription.push_back(new AlternateContentDescriptionItem(**it)); - it++; + resetRules(); + m_InstanceNumber = rhs.m_InstanceNumber; + m_ContentLabel = rhs.m_ContentLabel; + m_ContentDescription = rhs.m_ContentDescription; + m_ContentCreatorName = rhs.m_ContentCreatorName; + m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; + /* perform deep vector copy */ + OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); + while (it != rhs.m_AlternateContentDescription.end()) + { + m_AlternateContentDescription.push_back(new AlternateContentDescriptionItem(**it)); + it++; + } } - } } - OFCondition ContentIdentificationMacro::create(const OFString& instanceNumber, const OFString& contentLabel, const OFString& contentDescription, const OFString& contentCreatorName, ContentIdentificationMacro*& result) { - result = new ContentIdentificationMacro(); - if (!result) - return EC_MemoryExhausted; - OFCondition cond = result->setInstanceNumber(instanceNumber); - if (cond.good()) - { - cond = result->setContentLabel(contentLabel); - } - if (cond.good()) - { - cond = result->setContentDescription(contentDescription); - } - if (cond.good()) - { - cond = result->setContentCreatorName(contentCreatorName); - } - if (cond.good()) - { - cond = result->check(); - } - if (cond.bad()) - { - delete result; - result = NULL; - } - return cond; + result = new ContentIdentificationMacro(); + if (!result) + return EC_MemoryExhausted; + OFCondition cond = result->setInstanceNumber(instanceNumber); + if (cond.good()) + { + cond = result->setContentLabel(contentLabel); + } + if (cond.good()) + { + cond = result->setContentDescription(contentDescription); + } + if (cond.good()) + { + cond = result->setContentCreatorName(contentCreatorName); + } + if (cond.good()) + { + cond = result->check(); + } + if (cond.bad()) + { + delete result; + result = NULL; + } + return cond; } - - ContentIdentificationMacro& ContentIdentificationMacro::operator=(const ContentIdentificationMacro& rhs) { - if (&rhs != this) - { - this->clearData(); - m_InstanceNumber = rhs.m_InstanceNumber; - m_ContentLabel = rhs.m_ContentLabel; - m_ContentDescription = rhs.m_ContentDescription; - m_ContentCreatorName = rhs.m_ContentCreatorName; - m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; - /* perform deep vector copy */ - OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); - while (it != rhs.m_AlternateContentDescription.end()) + if (&rhs != this) { - AlternateContentDescriptionItem* newItem = new AlternateContentDescriptionItem(); - *newItem = **it; - m_AlternateContentDescription.push_back(newItem); - it++; + this->clearData(); + m_InstanceNumber = rhs.m_InstanceNumber; + m_ContentLabel = rhs.m_ContentLabel; + m_ContentDescription = rhs.m_ContentDescription; + m_ContentCreatorName = rhs.m_ContentCreatorName; + m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; + /* perform deep vector copy */ + OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); + while (it != rhs.m_AlternateContentDescription.end()) + { + AlternateContentDescriptionItem* newItem = new AlternateContentDescriptionItem(); + *newItem = **it; + m_AlternateContentDescription.push_back(newItem); + it++; + } } - } - return *this; + return *this; } - ContentIdentificationMacro::~ContentIdentificationMacro() { - clearData(); + clearData(); } - void ContentIdentificationMacro::clearData() { - m_InstanceNumber.clear(); - m_ContentLabel.clear(); - m_ContentDescription.clear(); - DcmIODUtil::freeContainer(m_AlternateContentDescription); - m_ContentCreatorName.clear(); - m_ContentCreatorIdentificationCode.clearData(); + m_InstanceNumber.clear(); + m_ContentLabel.clear(); + m_ContentDescription.clear(); + DcmIODUtil::freeContainer(m_AlternateContentDescription); + m_ContentCreatorName.clear(); + m_ContentCreatorIdentificationCode.clearData(); } - OFCondition ContentIdentificationMacro::check(const OFBool quiet) { - (void)quiet; - OFCondition result; - OFBool failure = m_ContentLabel.isEmpty() || m_InstanceNumber.isEmpty(); - if (!failure) - { - if (!m_AlternateContentDescription.empty()) // type 3 + (void)quiet; + OFCondition result; + OFBool failure = m_ContentLabel.isEmpty() || m_InstanceNumber.isEmpty(); + if (!failure) { - OFVector::iterator it = m_AlternateContentDescription.begin(); - while ( it != m_AlternateContentDescription.end() && !failure) - { - OFString str; - (*it)->getContentDescription(str).good(); // type 1 - failure = str.empty(); - if (!failure) + if (!m_AlternateContentDescription.empty()) // type 3 { - OFString meaning, value, designator; - (*it)->getLanguageCode().getCodeMeaning(meaning); - (*it)->getLanguageCode().getCodeValue(value); - (*it)->getLanguageCode().getCodeValue(designator); - failure = meaning.empty() || value.empty() || designator.empty(); + OFVector::iterator it = m_AlternateContentDescription.begin(); + while (it != m_AlternateContentDescription.end() && !failure) + { + OFString str; + (*it)->getContentDescription(str).good(); // type 1 + failure = str.empty(); + if (!failure) + { + OFString meaning, value, designator; + (*it)->getLanguageCode().getCodeMeaning(meaning); + (*it)->getLanguageCode().getCodeValue(value); + (*it)->getLanguageCode().getCodeValue(designator); + failure = meaning.empty() || value.empty() || designator.empty(); + } + it++; + } } - it++; - } } - } - if ( failure ) - result = EC_IllegalParameter; - return result; + if (failure) + result = EC_IllegalParameter; + return result; } - - -OFCondition ContentIdentificationMacro::getInstanceNumber(OFString& value, - const signed long pos) const +OFCondition ContentIdentificationMacro::getInstanceNumber(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_InstanceNumber, value, pos); + return DcmIODUtil::getStringValueFromElement(m_InstanceNumber, value, pos); } - - -OFCondition ContentIdentificationMacro::getContentLabel(OFString& value, - const signed long pos) const +OFCondition ContentIdentificationMacro::getContentLabel(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_ContentLabel, value, pos); + return DcmIODUtil::getStringValueFromElement(m_ContentLabel, value, pos); } - -OFCondition ContentIdentificationMacro::getContentDescription(OFString& value, - const signed long pos) const +OFCondition ContentIdentificationMacro::getContentDescription(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); + return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); } - -OFCondition ContentIdentificationMacro::getContentCreatorName(OFString& value, - const signed long pos) const +OFCondition ContentIdentificationMacro::getContentCreatorName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromElement(m_ContentCreatorName, value, pos); + return DcmIODUtil::getStringValueFromElement(m_ContentCreatorName, value, pos); } - CodeSequenceMacro& ContentIdentificationMacro::getContentCreatorIdentificationCode() { - return m_ContentCreatorIdentificationCode; + return m_ContentCreatorIdentificationCode; } - -OFVector& ContentIdentificationMacro::getAlternateContentDescription() +OFVector& +ContentIdentificationMacro::getAlternateContentDescription() { - return m_AlternateContentDescription; + return m_AlternateContentDescription; } - -OFCondition ContentIdentificationMacro::setInstanceNumber(const OFString& value, - const OFBool checkValue) +OFCondition ContentIdentificationMacro::setInstanceNumber(const OFString& value, const OFBool checkValue) { - OFCondition result; - if (checkValue) - { - result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - } - if (result.good()) - { - result = m_InstanceNumber.putOFStringArray(value); - } - return result; + OFCondition result; + if (checkValue) + { + result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + } + if (result.good()) + { + result = m_InstanceNumber.putOFStringArray(value); + } + return result; } - -OFCondition ContentIdentificationMacro::setContentLabel(const OFString& value, - const OFBool checkValue) +OFCondition ContentIdentificationMacro::setContentLabel(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentLabel)->getVM()) : EC_Normal; - if (result.good()) - result = m_ContentLabel.putOFStringArray(value); - return result; + OFCondition result = (checkValue) + ? DcmCodeString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentLabel)->getVM()) + : EC_Normal; + if (result.good()) + result = m_ContentLabel.putOFStringArray(value); + return result; } - -OFCondition ContentIdentificationMacro::setContentDescription(const OFString& value, - const OFBool checkValue) +OFCondition ContentIdentificationMacro::setContentDescription(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentDescription)->getVM()) : EC_Normal; - if (result.good()) - result = m_ContentDescription.putOFStringArray(value); - return result; + OFCondition result = (checkValue) + ? DcmLongString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentDescription)->getVM()) + : EC_Normal; + if (result.good()) + result = m_ContentDescription.putOFStringArray(value); + return result; } - -OFCondition ContentIdentificationMacro::setContentCreatorName(const OFString& value, - const OFBool checkValue) +OFCondition ContentIdentificationMacro::setContentCreatorName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, m_IODRules.getByTag(DCM_ContentCreatorName)->getVM()) : EC_Normal; - if (result.good()) - result = m_ContentCreatorName.putOFStringArray(value); - return result; + OFCondition result = (checkValue) + ? DcmPersonName::checkStringValue(value, m_IODRules.getByTag(DCM_ContentCreatorName)->getVM()) + : EC_Normal; + if (result.good()) + result = m_ContentCreatorName.putOFStringArray(value); + return result; } - -OFCondition ContentIdentificationMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition ContentIdentificationMacro::read(DcmItem& source, const OFBool clearOldData) { - OFCondition result; + OFCondition result; - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - /* flat elements */ + /* flat elements */ - DcmIODUtil::getAndCheckElementFromDataset(source, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); - DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); - DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); - DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); + DcmIODUtil::getAndCheckElementFromDataset(source, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); + DcmIODUtil::getAndCheckElementFromDataset( + source, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); + DcmIODUtil::getAndCheckElementFromDataset( + source, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); - /* sub sequences */ - IODRule *rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); - DcmIODUtil::readSubSequence > - ( source, - DCM_AlternateContentDescriptionSequence, - m_AlternateContentDescription, - rule->getVM(), - rule->getType(), - "ContentIdentificationMacro" ); + /* sub sequences */ + IODRule* rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); + DcmIODUtil::readSubSequence >(source, + DCM_AlternateContentDescriptionSequence, + m_AlternateContentDescription, + rule->getVM(), + rule->getType(), + "ContentIdentificationMacro"); - rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); - DcmIODUtil::readSingleItem - ( - source, - DCM_ContentCreatorIdentificationCodeSequence, - m_ContentCreatorIdentificationCode, - rule->getType(), - "ContentIdentificationMacro"); + rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); + DcmIODUtil::readSingleItem(source, + DCM_ContentCreatorIdentificationCodeSequence, + m_ContentCreatorIdentificationCode, + rule->getType(), + "ContentIdentificationMacro"); - return result; + return result; } - OFCondition ContentIdentificationMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; - - /* flat elements */ - DcmIODUtil::copyElementToDataset(result, item, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); - DcmIODUtil::copyElementToDataset(result, item, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); - DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); - DcmIODUtil::copyElementToDataset(result, item, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); - - IODRule *rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); - DcmIODUtil::writeSingleItem - ( - result, - DCM_ContentCreatorIdentificationCodeSequence, - m_ContentCreatorIdentificationCode, - item, - rule->getType(), - "ContentIdentificationMacro" - ); - - rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); - DcmIODUtil::writeSubSequence< OFVector > - ( - result, - DCM_AlternateContentDescriptionSequence, - m_AlternateContentDescription, - item, - rule->getVM(), - rule->getType(), - "ContentIdentificationMacro" - ); - - return result; + OFCondition result = EC_Normal; + + /* flat elements */ + DcmIODUtil::copyElementToDataset(result, item, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); + + IODRule* rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); + DcmIODUtil::writeSingleItem(result, + DCM_ContentCreatorIdentificationCodeSequence, + m_ContentCreatorIdentificationCode, + item, + rule->getType(), + "ContentIdentificationMacro"); + + rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); + DcmIODUtil::writeSubSequence >( + result, + DCM_AlternateContentDescriptionSequence, + m_AlternateContentDescription, + item, + rule->getVM(), + rule->getType(), + "ContentIdentificationMacro"); + return result; } - // ---------------- ContentIdentificationMacro::AlternateContentDescriptionItem ----------------- ContentIdentificationMacro::AlternateContentDescriptionItem::AlternateContentDescriptionItem() - : m_ContentDescription(DCM_ContentDescription), - m_LanguageCode() + : m_ContentDescription(DCM_ContentDescription) + , m_LanguageCode() { - // nothing to do + // nothing to do } - ContentIdentificationMacro::AlternateContentDescriptionItem::~AlternateContentDescriptionItem() { - m_LanguageCode.clearData(); + m_LanguageCode.clearData(); } - void ContentIdentificationMacro::AlternateContentDescriptionItem::clearData() { - m_ContentDescription.clear(); - m_LanguageCode.clearData(); + m_ContentDescription.clear(); + m_LanguageCode.clearData(); } - OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::read(DcmItem& source, const OFBool clearOldData) { - OFCondition result; - if (clearOldData) - clearData(); + OFCondition result; + if (clearOldData) + clearData(); - DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); - DcmIODUtil::readSingleItem - ( - source, - DCM_LanguageCodeSequence, - m_LanguageCode, - "1", - "ContentIdentificationMacro" - ); + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); + DcmIODUtil::readSingleItem( + source, DCM_LanguageCodeSequence, m_LanguageCode, "1", "ContentIdentificationMacro"); - return result; + return result; } - -OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::getContentDescription(OFString& value, - const long signed int pos) +OFCondition +ContentIdentificationMacro::AlternateContentDescriptionItem::getContentDescription(OFString& value, + const long signed int pos) { - return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); + return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); } - - CodeSequenceMacro& ContentIdentificationMacro::AlternateContentDescriptionItem::getLanguageCode() { - return m_LanguageCode; + return m_LanguageCode; } - - OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::write(DcmItem& item) { - OFCondition result = EC_Normal; - // write to item - DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); - DcmIODUtil::writeSingleItem - ( result, - DCM_LanguageCodeSequence, - m_LanguageCode, - item, - "1", - "ContentIdentificationMacro" - ); - return result; + OFCondition result = EC_Normal; + // write to item + DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); + DcmIODUtil::writeSingleItem( + result, DCM_LanguageCodeSequence, m_LanguageCode, item, "1", "ContentIdentificationMacro"); + return result; } - OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::setContentDescription(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_ContentDescription.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ContentDescription.putOFStringArray(value); + return result; } - // -------------------- HL7HierarchicDesignatorMacro -------------------- - HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(IODComponent* parent) -: IODComponent(parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } -HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, +HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(OFshared_ptr item, + OFshared_ptr rules, IODComponent* parent) -: IODComponent(item, rules, parent) + : IODComponent(item, rules, parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityID(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityID, *m_Item, value, pos); } - OFCondition HL7HierarchicDesignatorMacro::getLocalNamespaceEntityID(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_LocalNamespaceEntityID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LocalNamespaceEntityID, *m_Item, value, pos); } - OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityIDType(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityIDType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityIDType, *m_Item, value, pos); } - OFString HL7HierarchicDesignatorMacro::getName() const { - return "HL7HierarchicDesignatorMacro"; + return "HL7HierarchicDesignatorMacro"; } - void HL7HierarchicDesignatorMacro::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_UniversalEntityID, "1","1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_LocalNamespaceEntityID, "1","1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_UniversalEntityIDType, "1","1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_UniversalEntityID, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_LocalNamespaceEntityID, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED), + OFTrue); + m_Rules->addRule(new IODRule(DCM_UniversalEntityIDType, "1", "1C", "getName()", DcmIODTypes::IE_UNDEFINED), OFTrue); } - -OFCondition HL7HierarchicDesignatorMacro::setLocalNamespaceEntityID(const OFString& value, - const OFBool checkValue) +OFCondition HL7HierarchicDesignatorMacro::setLocalNamespaceEntityID(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertOFStringArray(DCM_LocalNamespaceEntityID,value); + (void)checkValue; + return m_Item->putAndInsertOFStringArray(DCM_LocalNamespaceEntityID, value); } - -OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityID(const OFString& value, - const OFBool checkValue) +OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityID(const OFString& value, const OFBool checkValue) { - (void) checkValue; - return m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID,value); + (void)checkValue; + return m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID, value); } - -OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityIDType(const OFString& value, - const OFBool checkValue) +OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityIDType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID,value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID, value); + return result; } - // -------------------- Mandatory View and Slice Progression Direction Macro -------------------- - -MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, - IODComponent* parent) -: IODComponent(item, rules, parent), - m_ViewCodeSequence(), - m_ViewModifierCode() +MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro( + OFshared_ptr item, OFshared_ptr rules, IODComponent* parent) + : IODComponent(item, rules, parent) + , m_ViewCodeSequence() + , m_ViewModifierCode() { - resetRules(); + resetRules(); } - - MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent) -: IODComponent(parent), - m_ViewCodeSequence(), - m_ViewModifierCode() + : IODComponent(parent) + , m_ViewCodeSequence() + , m_ViewModifierCode() { - resetRules(); + resetRules(); } - OFString MandatoryViewAndSliceProgressionDirectionMacro::getName() const { - return "MandatoryViewAndSliceProgressionDirectionMacro"; + return "MandatoryViewAndSliceProgressionDirectionMacro"; } - void MandatoryViewAndSliceProgressionDirectionMacro::resetRules() { - m_Rules->addRule(new IODRule(DCM_ViewCodeSequence, "1","1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_ViewModifierCodeSequence, "1-n","2C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); - m_Rules->addRule(new IODRule(DCM_SliceProgressionDirection, "1","1C", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ViewCodeSequence, "1", "1", getName(), DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ViewModifierCodeSequence, "1-n", "2C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue); + m_Rules->addRule(new IODRule(DCM_SliceProgressionDirection, "1", "1C", getName(), DcmIODTypes::IE_UNDEFINED), + OFTrue); } - void MandatoryViewAndSliceProgressionDirectionMacro::clearData() { - DcmIODUtil::freeContainer(m_ViewModifierCode); - m_ViewCodeSequence.clearData(); - IODComponent::clearData(); + DcmIODUtil::freeContainer(m_ViewModifierCode); + m_ViewCodeSequence.clearData(); + IODComponent::clearData(); } - -OFCondition MandatoryViewAndSliceProgressionDirectionMacro::read(DcmItem& source, - const OFBool clearOldData) +OFCondition MandatoryViewAndSliceProgressionDirectionMacro::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - { - m_ViewCodeSequence.clearData(); - DcmIODUtil::freeContainer(m_ViewModifierCode); - } - OFCondition result = EC_Normal; - DcmIODUtil::readSingleItem(source, DCM_ViewCodeSequence, m_ViewCodeSequence, m_Rules->getByTag(DCM_ViewCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_ViewCodeSequence, m_ViewModifierCode, m_Rules->getByTag(DCM_ViewCodeSequence)); - IODComponent::read(source, clearOldData); - return EC_Normal; + if (clearOldData) + { + m_ViewCodeSequence.clearData(); + DcmIODUtil::freeContainer(m_ViewModifierCode); + } + OFCondition result = EC_Normal; + DcmIODUtil::readSingleItem( + source, DCM_ViewCodeSequence, m_ViewCodeSequence, m_Rules->getByTag(DCM_ViewCodeSequence)); + DcmIODUtil::readSubSequence( + source, DCM_ViewCodeSequence, m_ViewModifierCode, m_Rules->getByTag(DCM_ViewCodeSequence)); + IODComponent::read(source, clearOldData); + return EC_Normal; } - OFCondition MandatoryViewAndSliceProgressionDirectionMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; - DcmIODUtil::writeSingleItem(result, DCM_ViewCodeSequence, m_ViewCodeSequence, *m_Item, m_Rules->getByTag(DCM_ViewCodeSequence)); - DcmIODUtil::writeSubSequence(result, DCM_ViewCodeSequence, m_ViewModifierCode, *m_Item, m_Rules->getByTag(DCM_ViewModifierCodeSequence)); - if (result.good()) result = IODComponent::write(item); - return result; + OFCondition result = EC_Normal; + DcmIODUtil::writeSingleItem( + result, DCM_ViewCodeSequence, m_ViewCodeSequence, *m_Item, m_Rules->getByTag(DCM_ViewCodeSequence)); + DcmIODUtil::writeSubSequence( + result, DCM_ViewCodeSequence, m_ViewModifierCode, *m_Item, m_Rules->getByTag(DCM_ViewModifierCodeSequence)); + if (result.good()) + result = IODComponent::write(item); + return result; } - CodeSequenceMacro& MandatoryViewAndSliceProgressionDirectionMacro::getViewCode() { - return m_ViewCodeSequence; + return m_ViewCodeSequence; } - -OFVector< CodeSequenceMacro* >& MandatoryViewAndSliceProgressionDirectionMacro::getViewModifierCode() +OFVector& MandatoryViewAndSliceProgressionDirectionMacro::getViewModifierCode() { - return m_ViewModifierCode; + return m_ViewModifierCode; } diff --git a/dcmiod/libsrc/iodreferences.cc b/dcmiod/libsrc/iodreferences.cc index bf57c13f..0eb1b540 100644 --- a/dcmiod/libsrc/iodreferences.cc +++ b/dcmiod/libsrc/iodreferences.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,534 +19,503 @@ * */ -#include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmiod/iodtypes.h" #include "dcmtk/dcmiod/iodreferences.h" -#include "dcmtk/dcmiod/iodutil.h" -#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcdatset.h" -#include "dcmtk/dcmdata/dcvrui.h" -#include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcerror.h" #include "dcmtk/dcmdata/dcfilefo.h" - +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmiod/iodutil.h" // ------------------- class IODReference ------------------------------- IODReference::IODReference(const IODReference::MAX_LEVEL level) -: m_PatientID(), - m_StudyInstanceUID(), - m_SeriesInstanceUID(), - m_SOPClassUID(), - m_SOPInstanceUID(), - m_Level(level) + : m_PatientID() + , m_StudyInstanceUID() + , m_SeriesInstanceUID() + , m_SOPClassUID() + , m_SOPInstanceUID() + , m_Level(level) { } - IODReference::IODReference() -: m_PatientID(), - m_StudyInstanceUID(), - m_SeriesInstanceUID(), - m_SOPClassUID(), - m_SOPInstanceUID(), - m_Level(LEVEL_STUDY) + : m_PatientID() + , m_StudyInstanceUID() + , m_SeriesInstanceUID() + , m_SOPClassUID() + , m_SOPInstanceUID() + , m_Level(LEVEL_STUDY) { } IODReference::~IODReference() { - // nothing to do + // nothing to do } - - void IODReference::clear() { - m_StudyInstanceUID.clear(); - m_SeriesInstanceUID.clear(); - m_SOPClassUID.clear(); - m_SOPInstanceUID.clear(); + m_StudyInstanceUID.clear(); + m_SeriesInstanceUID.clear(); + m_SOPClassUID.clear(); + m_SOPInstanceUID.clear(); } - OFBool IODReferences::add(IODReference* ref) { - if (ref->check().good()) - { - m_References.push_back(ref); - return OFTrue; - } - return OFFalse; + if (ref->check().good()) + { + m_References.push_back(ref); + return OFTrue; + } + return OFFalse; } - OFBool IODReference::readFromItem(DcmItem& item) { - if (m_Level >= LEVEL_PATIENT) - { - item.findAndGetOFString(DCM_PatientID, m_PatientID); - } - if (m_Level >= LEVEL_STUDY) - { - item.findAndGetOFString(DCM_StudyInstanceUID, m_StudyInstanceUID); - } - if (m_Level >= LEVEL_SERIES) - { - item.findAndGetOFString(DCM_SeriesInstanceUID, m_SeriesInstanceUID); - } - if (m_Level >= LEVEL_INSTANCE) - { - item.findAndGetOFString(DCM_SOPClassUID, m_SOPClassUID); - item.findAndGetOFString(DCM_SOPInstanceUID, m_SOPInstanceUID); - } - return check().good(); + if (m_Level >= LEVEL_PATIENT) + { + item.findAndGetOFString(DCM_PatientID, m_PatientID); + } + if (m_Level >= LEVEL_STUDY) + { + item.findAndGetOFString(DCM_StudyInstanceUID, m_StudyInstanceUID); + } + if (m_Level >= LEVEL_SERIES) + { + item.findAndGetOFString(DCM_SeriesInstanceUID, m_SeriesInstanceUID); + } + if (m_Level >= LEVEL_INSTANCE) + { + item.findAndGetOFString(DCM_SOPClassUID, m_SOPClassUID); + item.findAndGetOFString(DCM_SOPInstanceUID, m_SOPInstanceUID); + } + return check().good(); } - OFBool IODReference::readFromFile(const OFString& filename) { - clear(); - DcmFileFormat ff; - OFCondition result = ff.loadFile(filename.c_str()); - if (result.good()) - { - DcmDataset* dset = ff.getDataset(); - return readFromItem(*dset); - } - return OFFalse; + clear(); + DcmFileFormat ff; + OFCondition result = ff.loadFile(filename.c_str()); + if (result.good()) + { + DcmDataset* dset = ff.getDataset(); + return readFromItem(*dset); + } + return OFFalse; } - OFCondition IODReferences::readTractographyReferencedInstanceSequence(DcmItem& source) { - size_t omitted = 0; - size_t added = 0; - DcmSequenceOfItems *seq = NULL; - OFCondition result = source.findAndGetSequence(DCM_ReferencedInstanceSequence, seq); - if (result.good()) - { - DcmItem* item = NULL; - item = OFstatic_cast(DcmItem*, seq->nextInContainer(item)); - while ( (item != NULL) && result.good() ) + size_t omitted = 0; + size_t added = 0; + DcmSequenceOfItems* seq = NULL; + OFCondition result = source.findAndGetSequence(DCM_ReferencedInstanceSequence, seq); + if (result.good()) { - IODImageReference* ref = new IODImageReference(IODReference::LEVEL_INSTANCE); - if (!ref) - { - return EC_MemoryExhausted; - } - item->findAndGetOFString(DCM_ReferencedSOPClassUID, ref->m_SOPClassUID); - item->findAndGetOFString(DCM_ReferencedSOPInstanceUID, ref->m_SOPInstanceUID); - // if present, copy referenced frame numbers - DcmElement* elem = NULL; - if (item->findAndGetElement(DCM_ReferencedFrameNumber, elem).good()) - { - unsigned long vm = elem->getNumberOfValues(); - for (unsigned long f = 0; f < vm; f++) + DcmItem* item = NULL; + item = OFstatic_cast(DcmItem*, seq->nextInContainer(item)); + while ((item != NULL) && result.good()) { - Sint32 val = 0; - if (elem->getSint32(val, f).good()) - { - if (val >= 0) - ref->m_ReferencedFrameNumber.push_back( OFstatic_cast(Uint32, val) ); + IODImageReference* ref = new IODImageReference(IODReference::LEVEL_INSTANCE); + if (!ref) + { + return EC_MemoryExhausted; + } + item->findAndGetOFString(DCM_ReferencedSOPClassUID, ref->m_SOPClassUID); + item->findAndGetOFString(DCM_ReferencedSOPInstanceUID, ref->m_SOPInstanceUID); + // if present, copy referenced frame numbers + DcmElement* elem = NULL; + if (item->findAndGetElement(DCM_ReferencedFrameNumber, elem).good()) + { + unsigned long vm = elem->getNumberOfValues(); + for (unsigned long f = 0; f < vm; f++) + { + Sint32 val = 0; + if (elem->getSint32(val, f).good()) + { + if (val >= 0) + ref->m_ReferencedFrameNumber.push_back(OFstatic_cast(Uint32, val)); + else + { + DCMIOD_WARN("Referenced Frame Number must be > 0 but is " << val + << ", omitting frame reference"); + } + } + else + { + DCMIOD_WARN("Cannot get Referenced Frame Number from position #" + << f << " omitting frame reference"); + } + } + } + result = ref->check(); + if (result.good()) + { + added++; + m_References.push_back(ref); + } else { - DCMIOD_WARN("Referenced Frame Number must be > 0 but is " << val << ", omitting frame reference"); + DCMIOD_WARN("Could not read Image reference (invalid?): " << (*ref).toString()); + omitted++; + delete ref; + ref = NULL; } - } - else - { - DCMIOD_WARN("Cannot get Referenced Frame Number from position #" << f << " omitting frame reference"); - } + item = OFstatic_cast(DcmItem*, seq->nextInContainer(item)); } - } - result = ref->check(); - if (result.good()) - { - added++; - m_References.push_back(ref); - } - else - { - DCMIOD_WARN("Could not read Image reference (invalid?): " << (*ref).toString()); - omitted++; - delete ref; - ref = NULL; - } - item = OFstatic_cast(DcmItem*, seq->nextInContainer(item)); } - } - if ( (omitted > 0) && (added > 0) ) - { - return IOD_EC_ReferencesOmitted; - } - else if (omitted > 0) - { - return IOD_EC_InvalidReference; - } - return EC_Normal; -} - - - -OFCondition IODReferences::writeTractographyReferencedInstanceSequence(DcmItem& item) -{ - OFVector::iterator it = m_References.begin(); - item.findAndDeleteElement(DCM_ReferencedInstanceSequence); - DcmItem *seqItem = NULL; - size_t numItem = 0; - OFCondition result; - while ( (it != m_References.end() && result.good()) ) - { - if (result.good()) + if ((omitted > 0) && (added > 0)) { - result = item.findOrCreateSequenceItem(DCM_ReferencedInstanceSequence, seqItem, OFstatic_cast(long, numItem)); - numItem++; + return IOD_EC_ReferencesOmitted; } - if (result.good()) + else if (omitted > 0) { - result = seqItem->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, (*it)->m_SOPClassUID); + return IOD_EC_InvalidReference; } - if (result.good()) result = seqItem->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, (*it)->m_SOPInstanceUID); - if (result.good()) + return EC_Normal; +} + +OFCondition IODReferences::writeTractographyReferencedInstanceSequence(DcmItem& item) +{ + OFVector::iterator it = m_References.begin(); + item.findAndDeleteElement(DCM_ReferencedInstanceSequence); + DcmItem* seqItem = NULL; + size_t numItem = 0; + OFCondition result; + while ((it != m_References.end() && result.good())) { - if ( (*it)->getType() == IODReference::IMAGE ) - { if (result.good()) { - IODImageReference* ref = OFstatic_cast(IODImageReference*, *it); - if (ref && !ref->m_ReferencedFrameNumber.empty()) - { - OFStringStream oss; - for (size_t f = 0; f < ref->m_ReferencedFrameNumber.size(); f++) + result + = item.findOrCreateSequenceItem(DCM_ReferencedInstanceSequence, seqItem, OFstatic_cast(long, numItem)); + numItem++; + } + if (result.good()) + { + result = seqItem->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, (*it)->m_SOPClassUID); + } + if (result.good()) + result = seqItem->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, (*it)->m_SOPInstanceUID); + if (result.good()) + { + if ((*it)->getType() == IODReference::IMAGE) { - oss << ref->m_ReferencedFrameNumber[f] << "\\"; + if (result.good()) + { + IODImageReference* ref = OFstatic_cast(IODImageReference*, *it); + if (ref && !ref->m_ReferencedFrameNumber.empty()) + { + OFStringStream oss; + for (size_t f = 0; f < ref->m_ReferencedFrameNumber.size(); f++) + { + oss << ref->m_ReferencedFrameNumber[f] << "\\"; + } + OFSTRINGSTREAM_GETOFSTRING(oss, frameRefs) + // Insert all references into Referenced Frame Number attribute. + // Remove superfluous "\" at the end of the string. + result = seqItem->putAndInsertOFStringArray(DCM_ReferencedFrameNumber, + frameRefs.substr(0, frameRefs.size() - 1)); + } + } } - OFSTRINGSTREAM_GETOFSTRING(oss, frameRefs) - // Insert all references into Referenced Frame Number attribute. - // Remove superfluous "\" at the end of the string. - result = seqItem->putAndInsertOFStringArray(DCM_ReferencedFrameNumber, frameRefs.substr(0, frameRefs.size() - 1)); - } } - } + it++; } - it++; - } - if (result.bad()) - { - item.findAndDeleteElement(DCM_ReferencedInstanceSequence); - } - return result; + if (result.bad()) + { + item.findAndDeleteElement(DCM_ReferencedInstanceSequence); + } + return result; } - OFString IODReference::toString() const { - char buf[400]; - sprintf(buf, "Study/Series/SOPClass/SOPInstance UIDs: %s/%s/%s/%s", m_StudyInstanceUID.c_str(), m_SeriesInstanceUID.c_str(), m_SOPClassUID.c_str(), m_SOPInstanceUID.c_str()); - return buf; + char buf[400]; + sprintf(buf, + "Study/Series/SOPClass/SOPInstance UIDs: %s/%s/%s/%s", + m_StudyInstanceUID.c_str(), + m_SeriesInstanceUID.c_str(), + m_SOPClassUID.c_str(), + m_SOPInstanceUID.c_str()); + return buf; } - OFCondition IODReference::check() const { - OFCondition result; - if (m_Level >= LEVEL_PATIENT) - { - if (!m_PatientID.empty()) - { - result = DcmLongString::checkStringValue(m_PatientID); - } - else - { - result = IOD_EC_InvalidElementValue; - } - } - if (result.good() && (m_Level >= LEVEL_STUDY)) - { - if (!m_StudyInstanceUID.empty()) - { - result= DcmUniqueIdentifier::checkStringValue(m_StudyInstanceUID, "1"); - } - else - { - result = IOD_EC_InvalidElementValue; - } - } - if (result.good() && (m_Level >= LEVEL_SERIES)) - { - if (!m_SeriesInstanceUID.empty()) - { - result = DcmUniqueIdentifier::checkStringValue(m_SeriesInstanceUID, "1"); - } - else + OFCondition result; + if (m_Level >= LEVEL_PATIENT) { - result = IOD_EC_InvalidElementValue; + if (!m_PatientID.empty()) + { + result = DcmLongString::checkStringValue(m_PatientID); + } + else + { + result = IOD_EC_InvalidElementValue; + } } - } - if (result.good() && (m_Level >= LEVEL_INSTANCE)) - { - if (!m_SOPClassUID.empty()) + if (result.good() && (m_Level >= LEVEL_STUDY)) { - result = DcmUniqueIdentifier::checkStringValue(m_SOPClassUID, "1"); + if (!m_StudyInstanceUID.empty()) + { + result = DcmUniqueIdentifier::checkStringValue(m_StudyInstanceUID, "1"); + } + else + { + result = IOD_EC_InvalidElementValue; + } } - else + if (result.good() && (m_Level >= LEVEL_SERIES)) { - result = IOD_EC_InvalidElementValue; + if (!m_SeriesInstanceUID.empty()) + { + result = DcmUniqueIdentifier::checkStringValue(m_SeriesInstanceUID, "1"); + } + else + { + result = IOD_EC_InvalidElementValue; + } } - } - if (result.good() && (m_Level >= LEVEL_INSTANCE)) - { - if (!m_SOPInstanceUID.empty()) + if (result.good() && (m_Level >= LEVEL_INSTANCE)) { - result = DcmUniqueIdentifier::checkStringValue(m_SOPInstanceUID, "1"); + if (!m_SOPClassUID.empty()) + { + result = DcmUniqueIdentifier::checkStringValue(m_SOPClassUID, "1"); + } + else + { + result = IOD_EC_InvalidElementValue; + } } - else + if (result.good() && (m_Level >= LEVEL_INSTANCE)) { - result = IOD_EC_InvalidElementValue; + if (!m_SOPInstanceUID.empty()) + { + result = DcmUniqueIdentifier::checkStringValue(m_SOPInstanceUID, "1"); + } + else + { + result = IOD_EC_InvalidElementValue; + } } - } - return result; + return result; } - IODReference* IODReference::clone() const { - IODReference* ref = new IODReference(); - if (ref) - { - ref->m_PatientID = m_PatientID; - ref->m_StudyInstanceUID = m_StudyInstanceUID; - ref->m_SeriesInstanceUID = m_SeriesInstanceUID; - ref->m_SOPClassUID = m_SOPClassUID; - ref->m_SOPInstanceUID = m_SOPInstanceUID; - ref->m_Level = m_Level; - } - return ref; + IODReference* ref = new IODReference(); + if (ref) + { + ref->m_PatientID = m_PatientID; + ref->m_StudyInstanceUID = m_StudyInstanceUID; + ref->m_SeriesInstanceUID = m_SeriesInstanceUID; + ref->m_SOPClassUID = m_SOPClassUID; + ref->m_SOPInstanceUID = m_SOPInstanceUID; + ref->m_Level = m_Level; + } + return ref; } - // ------------------- class IODImageReference ------------------------------- - IODImageReference::IODImageReference(const IODReference::MAX_LEVEL level) -: IODReference(level), - m_ReferencedFrameNumber() + : IODReference(level) + , m_ReferencedFrameNumber() { } IODImageReference::IODImageReference() -: IODReference(LEVEL_INSTANCE), - m_ReferencedFrameNumber() + : IODReference(LEVEL_INSTANCE) + , m_ReferencedFrameNumber() { - } - IODImageReference::IODImageReference(const OFString& patientID, const OFString& studyUID, const OFString& seriesUID, const OFString& sopInstanceUID, const OFString& sopClassUID, const OFVector& refFrameNumbers) -: IODReference(LEVEL_INSTANCE), - m_ReferencedFrameNumber(refFrameNumbers) + : IODReference(LEVEL_INSTANCE) + , m_ReferencedFrameNumber(refFrameNumbers) { - m_PatientID = patientID; - m_StudyInstanceUID = studyUID; - m_SeriesInstanceUID = seriesUID; - m_SOPInstanceUID = sopInstanceUID; - m_SOPClassUID = sopClassUID; + m_PatientID = patientID; + m_StudyInstanceUID = studyUID; + m_SeriesInstanceUID = seriesUID; + m_SOPInstanceUID = sopInstanceUID; + m_SOPClassUID = sopClassUID; } - IODImageReference::IODImageReference(const OFString& patientID, const OFString& studyUID, const OFString& seriesUID, const OFString& sopInstanceUID, const OFString& sopClassUID) -: m_ReferencedFrameNumber() + : m_ReferencedFrameNumber() { - m_PatientID = patientID; - m_StudyInstanceUID = studyUID; - m_SeriesInstanceUID = seriesUID; - m_SOPInstanceUID = sopInstanceUID; - m_SOPClassUID = sopClassUID; + m_PatientID = patientID; + m_StudyInstanceUID = studyUID; + m_SeriesInstanceUID = seriesUID; + m_SOPInstanceUID = sopInstanceUID; + m_SOPClassUID = sopClassUID; } - - IODReference* IODImageReference::clone() const { - IODImageReference* ref = new IODImageReference(m_Level); - if (ref) - { - *(OFstatic_cast(IODReference*, ref)) = *this; - ref->m_ReferencedFrameNumber = m_ReferencedFrameNumber; - } - return ref; + IODImageReference* ref = new IODImageReference(m_Level); + if (ref) + { + *(OFstatic_cast(IODReference*, ref)) = *this; + ref->m_ReferencedFrameNumber = m_ReferencedFrameNumber; + } + return ref; } - void IODImageReference::clear() { - IODReference::clear(); - m_ReferencedFrameNumber.clear(); + IODReference::clear(); + m_ReferencedFrameNumber.clear(); } - -OFBool IODImageReference::readFromFile(const OFString& filename, - const OFVector< Uint32 > frameNumbers) +OFBool IODImageReference::readFromFile(const OFString& filename, const OFVector frameNumbers) { - clear(); - DcmFileFormat ff; - OFCondition result = ff.loadFile(filename.c_str()); - if (result.good()) - { - if ( readFromItem( *ff.getDataset() ) ) + clear(); + DcmFileFormat ff; + OFCondition result = ff.loadFile(filename.c_str()); + if (result.good()) { - m_ReferencedFrameNumber = frameNumbers; - return OFTrue; + if (readFromItem(*ff.getDataset())) + { + m_ReferencedFrameNumber = frameNumbers; + return OFTrue; + } } - } - return OFFalse; + return OFFalse; } - // ------------------ class IODSegmentationReference --------------------------- IODSegmentationReference::IODSegmentationReference(const IODReference::MAX_LEVEL level) -: IODReference(level), - m_ReferencedSegmentNumber() + : IODReference(level) + , m_ReferencedSegmentNumber() { } - IODSegmentationReference::IODSegmentationReference() -: IODReference(LEVEL_INSTANCE), - m_ReferencedSegmentNumber() + : IODReference(LEVEL_INSTANCE) + , m_ReferencedSegmentNumber() { - } - IODReference* IODSegmentationReference::clone() const { - IODSegmentationReference* ref = new IODSegmentationReference(m_Level); - if (ref) - { - *(OFstatic_cast(IODReference*, ref)) = *this; - ref->m_ReferencedSegmentNumber = m_ReferencedSegmentNumber; - } - return ref; + IODSegmentationReference* ref = new IODSegmentationReference(m_Level); + if (ref) + { + *(OFstatic_cast(IODReference*, ref)) = *this; + ref->m_ReferencedSegmentNumber = m_ReferencedSegmentNumber; + } + return ref; } - -OFBool IODSegmentationReference::readFromFile(const OFString& filename, - const OFVector< Uint16 > segmentNumbers) +OFBool IODSegmentationReference::readFromFile(const OFString& filename, const OFVector segmentNumbers) { - clear(); - DcmFileFormat ff; - OFCondition result = ff.loadFile(filename.c_str()); - if (result.good()) - { - if ( readFromItem(*ff.getDataset()) ) + clear(); + DcmFileFormat ff; + OFCondition result = ff.loadFile(filename.c_str()); + if (result.good()) { - m_ReferencedSegmentNumber = segmentNumbers; - return OFTrue; + if (readFromItem(*ff.getDataset())) + { + m_ReferencedSegmentNumber = segmentNumbers; + return OFTrue; + } } - } - return OFFalse; + return OFFalse; } - void IODSegmentationReference::clear() { - IODReference::clear(); - m_ReferencedSegmentNumber.clear(); + IODReference::clear(); + m_ReferencedSegmentNumber.clear(); } - - IODReferences::IODReferences() -: m_References() + : m_References() { - // nothing to do + // nothing to do } - IODReferences::~IODReferences() { - DcmIODUtil::freeContainer(m_References); + DcmIODUtil::freeContainer(m_References); } - IODReferences::IODReferences(const IODReferences& rhs) -: m_References() + : m_References() { - *this = rhs; + *this = rhs; } - -IODReferences & IODReferences::operator=(const IODReferences& rhs) +IODReferences& IODReferences::operator=(const IODReferences& rhs) { - if (&rhs == this) - return *this; + if (&rhs == this) + return *this; - OFVector::const_iterator ref = rhs.m_References.begin(); - while (ref != rhs.m_References.end()) - { - m_References.push_back( (*ref)->clone()); - ref++; - } - return *this; + OFVector::const_iterator ref = rhs.m_References.begin(); + while (ref != rhs.m_References.end()) + { + m_References.push_back((*ref)->clone()); + ref++; + } + return *this; } - - const OFVector& IODReferences::get() const { - return m_References; + return m_References; } - size_t IODReferences::size() const { - return m_References.size(); + return m_References.size(); } - -size_t IODReferences::addFromFiles(const OFVector< OFString >& dcmFiles, - const IODReference::MAX_LEVEL level) +size_t IODReferences::addFromFiles(const OFVector& dcmFiles, const IODReference::MAX_LEVEL level) { - if (dcmFiles.empty()) - { - return 0; - } - - OFCondition result; - OFVector::const_iterator it = dcmFiles.begin(); - size_t count = 0; - while (it != dcmFiles.end()) - { - IODReference* ref = new IODReference(level); - if (ref && ref->readFromFile(*it)) + if (dcmFiles.empty()) { - m_References.push_back(ref); - count++; + return 0; } - else + + OFCondition result; + OFVector::const_iterator it = dcmFiles.begin(); + size_t count = 0; + while (it != dcmFiles.end()) { - DCMIOD_WARN("Could not add references from file " << (*it) << " (skipping)"); - delete ref; + IODReference* ref = new IODReference(level); + if (ref && ref->readFromFile(*it)) + { + m_References.push_back(ref); + count++; + } + else + { + DCMIOD_WARN("Could not add references from file " << (*it) << " (skipping)"); + delete ref; + } + it++; } - it++; - } - return count; + return count; } - void IODReferences::clearData() { - DcmIODUtil::freeContainer(m_References); + DcmIODUtil::freeContainer(m_References); } diff --git a/dcmiod/libsrc/iodrules.cc b/dcmiod/libsrc/iodrules.cc index d9df261c..86740fa8 100644 --- a/dcmiod/libsrc/iodrules.cc +++ b/dcmiod/libsrc/iodrules.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,169 +19,158 @@ * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmiod/iodtypes.h" -#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmiod/iodtypes.h" - -IODRules::IODRules() : -m_Rules() +IODRules::IODRules() + : m_Rules() { - // nothing to do + // nothing to do } - IODRules* IODRules::clone() { - IODRules *newRules = new IODRules(); - if (newRules) - { - OFMap::iterator it = m_Rules.begin(); - while (it != m_Rules.end()) + IODRules* newRules = new IODRules(); + if (newRules) { - if (it->second) - { - IODRule* newRule = it->second->clone(); - if (newRule) - { - newRules->addRule(newRule); - } - else + OFMap::iterator it = m_Rules.begin(); + while (it != m_Rules.end()) { - DCMIOD_WARN("Cannot create new IODRule, memory exhausted?"); + if (it->second) + { + IODRule* newRule = it->second->clone(); + if (newRule) + { + newRules->addRule(newRule); + } + else + { + DCMIOD_WARN("Cannot create new IODRule, memory exhausted?"); + } + } + else + { + DCMIOD_WARN("Found NULL IODRule, cannot clone"); + } + it++; } - } - else - { - DCMIOD_WARN("Found NULL IODRule, cannot clone"); - } - it++; } - } - else - { - DCMIOD_WARN("Cannot create new IODRules, memory exhausted?"); - } - return newRules; + else + { + DCMIOD_WARN("Cannot create new IODRules, memory exhausted?"); + } + return newRules; } - IODRule* IODRules::getByTag(const DcmTagKey& key) const { - IODRules::const_iterator it = m_Rules.find(key); - if ( it != m_Rules.end() ) - return (*it).second; - else - return NULL; + IODRules::const_iterator it = m_Rules.find(key); + if (it != m_Rules.end()) + return (*it).second; + else + return NULL; } - IODRules::iterator IODRules::begin() { - return m_Rules.begin(); + return m_Rules.begin(); } IODRules::iterator IODRules::end() { - return m_Rules.end(); + return m_Rules.end(); } - void IODRules::clear() { - while (m_Rules.size() > 0) - { - IODRules::iterator it = m_Rules.begin(); - IODRule* rule = (*it).second; - m_Rules.erase(it); - delete rule; - rule = NULL; - } + while (m_Rules.size() > 0) + { + IODRules::iterator it = m_Rules.begin(); + IODRule* rule = (*it).second; + m_Rules.erase(it); + delete rule; + rule = NULL; + } } -OFBool IODRules::addRule(IODRule* rule, - const OFBool overwriteExisting) +OFBool IODRules::addRule(IODRule* rule, const OFBool overwriteExisting) { - if (rule == NULL) - { - DCMIOD_ERROR("Cannot add IOD rule: NULL pointer"); - return OFFalse; - } - DcmTagKey key = rule->getTagKey(); - iterator it = m_Rules.find(key); - if ( it != m_Rules.end() ) - { - if (overwriteExisting) + if (rule == NULL) { - delete (*it).second; - (*it).second = rule; + DCMIOD_ERROR("Cannot add IOD rule: NULL pointer"); + return OFFalse; + } + DcmTagKey key = rule->getTagKey(); + iterator it = m_Rules.find(key); + if (it != m_Rules.end()) + { + if (overwriteExisting) + { + delete (*it).second; + (*it).second = rule; + } + else + { + DCMIOD_DEBUG("IOD rule for tag " << key << " not inserted (already existing and overwriting disabled)"); + return OFFalse; + } } else { - DCMIOD_DEBUG("IOD rule for tag " << key << " not inserted (already existing and overwriting disabled)"); - return OFFalse; + m_Rules.insert(OFMake_pair(key, rule)); } - } - else - { - m_Rules.insert( OFMake_pair ( key, rule) ); - } - return OFTrue; + return OFTrue; } - -const OFVector< IODRule* > IODRules::getByModule(const OFString& moduleName) +const OFVector IODRules::getByModule(const OFString& moduleName) { - OFVector result; - IODRules::iterator it = m_Rules.begin(); - while (it != m_Rules.end()) - { - if ( (*it).second->getModule() == moduleName ) + OFVector result; + IODRules::iterator it = m_Rules.begin(); + while (it != m_Rules.end()) { - result.push_back((*it).second); + if ((*it).second->getModule() == moduleName) + { + result.push_back((*it).second); + } + it++; } - it++; - } - return result; + return result; } - OFBool IODRules::deleteRule(const DcmTagKey key) { - IODRules::iterator it = m_Rules.find(key); - if ( it != m_Rules.end() ) - { - IODRule* rule = (*it).second; - m_Rules.erase(it); - delete rule; - return OFTrue; - } - return OFFalse; + IODRules::iterator it = m_Rules.find(key); + if (it != m_Rules.end()) + { + IODRule* rule = (*it).second; + m_Rules.erase(it); + delete rule; + return OFTrue; + } + return OFFalse; } - -void IODRules::dump(STD_NAMESPACE ostream &out) +void IODRules::dump(STD_NAMESPACE ostream& out) { - IODRules::iterator it = m_Rules.begin(); - while ( it != m_Rules.end() ) - { - out << (*it).first << ": Type \"" << (*it).second->getType() << "\", VM \"" << (*it).second->getType() << "\"" << OFendl; - it++; - } + IODRules::iterator it = m_Rules.begin(); + while (it != m_Rules.end()) + { + out << (*it).first << ": Type \"" << (*it).second->getType() << "\", VM \"" << (*it).second->getType() << "\"" + << OFendl; + it++; + } } - IODRules::~IODRules() { - clear(); + clear(); } - - IODRule::IODRule(const DcmTagKey& key, const OFString& VM, const OFString& type, @@ -189,176 +178,167 @@ IODRule::IODRule(const DcmTagKey& key, const DcmIODTypes::IOD_IE ie, const OFString& defaultValue, const OFString& privateCreator) -: m_Key(key), -m_VM(VM), -m_Type(type), -m_Module(module), -m_IE(ie), -m_DefaultValue(defaultValue), -m_PrivateCreator(privateCreator) + : m_Key(key) + , m_VM(VM) + , m_Type(type) + , m_Module(module) + , m_IE(ie) + , m_DefaultValue(defaultValue) + , m_PrivateCreator(privateCreator) { - // nothing else to do + // nothing else to do } - IODRule::~IODRule() { - // nothing to do + // nothing to do } - IODRule* IODRule::clone() { - return new IODRule(m_Key, m_VM, m_Type, m_Module, m_IE, m_DefaultValue, m_PrivateCreator); + return new IODRule(m_Key, m_VM, m_Type, m_Module, m_IE, m_DefaultValue, m_PrivateCreator); } - - OFString IODRule::getPrivateCreator() const { - return m_PrivateCreator; + return m_PrivateCreator; } - DcmTagKey IODRule::getTagKey() const { - return m_Key; + return m_Key; } - - OFString IODRule::getModule() const { - return m_Module; + return m_Module; } - OFString IODRule::getType() const { - return m_Type; + return m_Type; } - OFString IODRule::getVM() const { - return m_VM; + return m_VM; } - OFString IODRule::getDefaultValue() const { - return m_DefaultValue; + return m_DefaultValue; } - -DcmIODTypes::IOD_IE IODRule::getIE() const +DcmIODTypes::IOD_IE IODRule::getIE() const { - return m_IE; + return m_IE; } - OFBool IODRule::setType(const OFString& val) { - if ( (val != "1") && (val != "1C") && (val != "2") && (val != "2C") && (val != "3") ) - { - return OFFalse; - } - m_Type = val; - return OFTrue; + if ((val != "1") && (val != "1C") && (val != "2") && (val != "2C") && (val != "3")) + { + return OFFalse; + } + m_Type = val; + return OFTrue; } - OFBool IODRule::setModule(const OFString& val) { - if (val.empty()) - { - return OFFalse; - } - m_Module = val; - return OFTrue; + if (val.empty()) + { + return OFFalse; + } + m_Module = val; + return OFTrue; } - - OFBool IODRule::setPrivateCreator(const OFString& val) { - if (val.empty()) - { - return OFFalse; - } - m_PrivateCreator = val; - return OFTrue; + if (val.empty()) + { + return OFFalse; + } + m_PrivateCreator = val; + return OFTrue; } - OFBool IODRule::setDefaultValue(const OFString& val) { - if (val.empty()) - { - return OFFalse; - } - m_DefaultValue = val; - return OFTrue; + if (val.empty()) + { + return OFFalse; + } + m_DefaultValue = val; + return OFTrue; } - OFBool IODRule::setVM(const OFString& val) { - // One could check whether this is a valid VM string... - m_VM = val; - return OFTrue; + // One could check whether this is a valid VM string... + m_VM = val; + return OFTrue; } - -OFCondition IODRule::check(DcmItem& item, - const OFBool quiet) +OFCondition IODRule::check(DcmItem& item, const OFBool quiet) { - OFCondition result; - const OFString tagName = DcmTag(m_Key).getTagName(); - DcmElement *elem = NULL; - OFCondition searchCond = item.findAndGetElement(m_Key, elem, OFFalse /* only this level */); - /* NB: type 1C and 2C cannot be checked, assuming to be optional */ - if (((m_Type == "1") || (m_Type== "2")) && searchCond.bad()) - { - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " absent in " << m_Module << " (type " << m_Type << ")"); - result = EC_MissingAttribute; - } - else if ((elem == NULL) || elem->isEmpty(OFTrue /*normalize*/)) - { - /* however, type 1C should never be present with empty value */ - if (((m_Type == "1") || (m_Type == "1C")) && searchCond.good()) + OFCondition result; + const OFString tagName = DcmTag(m_Key).getTagName(); + DcmElement* elem = NULL; + OFCondition searchCond = item.findAndGetElement(m_Key, elem, OFFalse /* only this level */); + /* NB: type 1C and 2C cannot be checked, assuming to be optional */ + if (((m_Type == "1") || (m_Type == "2")) && searchCond.bad()) { - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " empty in " << m_Module << " (type " << m_Type << ")"); - result = EC_MissingValue; + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << " absent in " << m_Module << " (type " << m_Type << ")"); + result = EC_MissingAttribute; } - } else { - const OFCondition checkResult = elem->checkValue(m_VM, OFTrue /*oldFormat*/); - if (checkResult == EC_InvalidCharacter) + else if ((elem == NULL) || elem->isEmpty(OFTrue /*normalize*/)) { - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " contains invalid character(s) in " << m_Module); - result = checkResult; - } - else if (checkResult == EC_ValueRepresentationViolated) - { - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " violates VR definition in " << m_Module); - result = checkResult; - } - else if (checkResult == EC_ValueMultiplicityViolated) - { - const OFString vmText = (elem->getVR() == EVR_SQ) ? " #items" : " VM"; - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << vmText << " != " << m_VM << " in " << m_Module); - result = checkResult; - } - else if (checkResult == EC_MaximumLengthViolated) - { - if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " violates maximum VR length in " << m_Module); - result = checkResult; + /* however, type 1C should never be present with empty value */ + if (((m_Type == "1") || (m_Type == "1C")) && searchCond.good()) + { + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << " empty in " << m_Module << " (type " << m_Type << ")"); + result = EC_MissingValue; + } } - else if (checkResult.bad()) + else { - if (!quiet) DCMIOD_DEBUG("INTERNAL ERROR while checking value of " << tagName << " " << m_Key << " in " << m_Module); - result = EC_InternalError; + const OFCondition checkResult = elem->checkValue(m_VM, OFTrue /*oldFormat*/); + if (checkResult == EC_InvalidCharacter) + { + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << " contains invalid character(s) in " << m_Module); + result = checkResult; + } + else if (checkResult == EC_ValueRepresentationViolated) + { + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << " violates VR definition in " << m_Module); + result = checkResult; + } + else if (checkResult == EC_ValueMultiplicityViolated) + { + const OFString vmText = (elem->getVR() == EVR_SQ) ? " #items" : " VM"; + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << vmText << " != " << m_VM << " in " << m_Module); + result = checkResult; + } + else if (checkResult == EC_MaximumLengthViolated) + { + if (!quiet) + DCMIOD_WARN(tagName << " " << m_Key << " violates maximum VR length in " << m_Module); + result = checkResult; + } + else if (checkResult.bad()) + { + if (!quiet) + DCMIOD_DEBUG("INTERNAL ERROR while checking value of " << tagName << " " << m_Key << " in " + << m_Module); + result = EC_InternalError; + } } - } - return result; + return result; } diff --git a/dcmiod/libsrc/iodtypes.cc b/dcmiod/libsrc/iodtypes.cc index 74dc4d9e..9ea5fce8 100644 --- a/dcmiod/libsrc/iodtypes.cc +++ b/dcmiod/libsrc/iodtypes.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,28 +19,29 @@ * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcerror.h" OFLogger DCM_dcmiodLogger = OFLog::getLogger("dcmtk.dcmiod"); - /*---------------------------------* * constant definitions *---------------------------------*/ // conditions -makeOFConditionConst(IOD_EC_WrongSOPClass, OFM_dcmiod, 1, OF_error, "Wrong SOP Class"); -makeOFConditionConst(IOD_EC_MissingAttribute, OFM_dcmiod, 2, OF_error, "Missing Attribute(s)"); -makeOFConditionConst(IOD_EC_MissingSequenceData, OFM_dcmiod, 3, OF_error, "Missing Sequence Data"); -makeOFConditionConst(IOD_EC_InvalidDimensions, OFM_dcmiod, 4, OF_error, "Invalid dimension information"); -makeOFConditionConst(IOD_EC_CannotInsertFrame, OFM_dcmiod, 5, OF_error, "Cannot insert frame"); -makeOFConditionConst(IOD_EC_InvalidPixelData, OFM_dcmiod, 6, OF_error, "Invalid Pixel Data"); -makeOFConditionConst(IOD_EC_InvalidObject, OFM_dcmiod, 7, OF_error, "Invalid Object"); -makeOFConditionConst(IOD_EC_CannotDecompress, OFM_dcmiod, 8, OF_error, "Cannot decompress"); -makeOFConditionConst(IOD_EC_NoSuchRule, OFM_dcmiod, 9, OF_error, "No such IOD rule"); -makeOFConditionConst(IOD_EC_InvalidLaterality, OFM_dcmiod, 10, OF_error, "Invalid value for 'Laterality' (only 'L' or 'R' permitted)"); -makeOFConditionConst(IOD_EC_InvalidElementValue, OFM_dcmiod, 11, OF_error, "Value not allowed for element"); -makeOFConditionConst(IOD_EC_InvalidReference, OFM_dcmiod, 12, OF_error, "One or more invalid SOP references"); -makeOFConditionConst(IOD_EC_ReferencesOmitted, OFM_dcmiod, 13, OF_error, "One or more SOP references have been omitted"); +makeOFConditionConst(IOD_EC_WrongSOPClass, OFM_dcmiod, 1, OF_error, "Wrong SOP Class"); +makeOFConditionConst(IOD_EC_MissingAttribute, OFM_dcmiod, 2, OF_error, "Missing Attribute(s)"); +makeOFConditionConst(IOD_EC_MissingSequenceData, OFM_dcmiod, 3, OF_error, "Missing Sequence Data"); +makeOFConditionConst(IOD_EC_InvalidDimensions, OFM_dcmiod, 4, OF_error, "Invalid dimension information"); +makeOFConditionConst(IOD_EC_CannotInsertFrame, OFM_dcmiod, 5, OF_error, "Cannot insert frame"); +makeOFConditionConst(IOD_EC_InvalidPixelData, OFM_dcmiod, 6, OF_error, "Invalid Pixel Data"); +makeOFConditionConst(IOD_EC_InvalidObject, OFM_dcmiod, 7, OF_error, "Invalid Object"); +makeOFConditionConst(IOD_EC_CannotDecompress, OFM_dcmiod, 8, OF_error, "Cannot decompress"); +makeOFConditionConst(IOD_EC_NoSuchRule, OFM_dcmiod, 9, OF_error, "No such IOD rule"); +makeOFConditionConst( + IOD_EC_InvalidLaterality, OFM_dcmiod, 10, OF_error, "Invalid value for 'Laterality' (only 'L' or 'R' permitted)"); +makeOFConditionConst(IOD_EC_InvalidElementValue, OFM_dcmiod, 11, OF_error, "Value not allowed for element"); +makeOFConditionConst(IOD_EC_InvalidReference, OFM_dcmiod, 12, OF_error, "One or more invalid SOP references"); +makeOFConditionConst( + IOD_EC_ReferencesOmitted, OFM_dcmiod, 13, OF_error, "One or more SOP references have been omitted"); diff --git a/dcmiod/libsrc/iodutil.cc b/dcmiod/libsrc/iodutil.cc index b951f8aa..c06680ce 100644 --- a/dcmiod/libsrc/iodutil.cc +++ b/dcmiod/libsrc/iodutil.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,445 +19,516 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/dcmdata/dctypes.h" // logger #include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctypes.h" // logger #include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmdata/dcmetinf.h" #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcdict.h" #include "dcmtk/dcmdata/dcdicent.h" -#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcdict.h" #include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcvrda.h" #include "dcmtk/dcmdata/dcvrtm.h" -#include "dcmtk/dcmdata/dcuid.h" -#include "dcmtk/dcmdata/dcitem.h" - // --- static helpers --- -OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement &delem, - const OFString &vm, - const OFString &type, - const char *moduleName) -{ - DcmStack stack; - const DcmTagKey tagKey = delem.getTag(); - OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); - if (result.good()) - { - /* copy object from search stack */ - result = delem.copyFrom(*stack.top()); - /* we need a reference to the original element in order to determine the SpecificCharacterSet */ - checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); - } - /* the element could not be found in the dataset */ - else - { - checkElementValue(delem, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); - } - return result; -} - - -OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, +OFCondition DcmIODUtil::getAndCheckElementFromDataset( + DcmItem& dataset, DcmElement& delem, const OFString& vm, const OFString& type, const char* moduleName) +{ + DcmStack stack; + const DcmTagKey tagKey = delem.getTag(); + OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (result.good()) + { + /* copy object from search stack */ + result = delem.copyFrom(*stack.top()); + /* we need a reference to the original element in order to determine the SpecificCharacterSet */ + checkElementValue(OFstatic_cast(DcmElement*, stack.top()), + tagKey, + vm, + type, + result, + moduleName, + dcmtk::log4cplus::WARN_LOG_LEVEL); + } + /* the element could not be found in the dataset */ + else + { + checkElementValue(delem, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); + } + return result; +} + +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem& dataset, const DcmTagKey& tagKey, DcmElement*& delem, - const OFString &vm, - const OFString &type, - const char *moduleName) + const OFString& vm, + const OFString& type, + const char* moduleName) { - if (delem) - return EC_IllegalParameter; + if (delem) + return EC_IllegalParameter; - DcmStack stack; - OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); - if (result.good()) - { - /* copy object from search stack */ - delem = OFstatic_cast ( DcmElement*, stack.top()->clone() ); - /* we need a reference to the original element in order to determine the SpecificCharacterSet */ - checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); - } - /* the element could not be found in the dataset */ - else - checkElementValue(delem, tagKey, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); + DcmStack stack; + OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (result.good()) + { + /* copy object from search stack */ + delem = OFstatic_cast(DcmElement*, stack.top()->clone()); + /* we need a reference to the original element in order to determine the SpecificCharacterSet */ + checkElementValue(OFstatic_cast(DcmElement*, stack.top()), + tagKey, + vm, + type, + result, + moduleName, + dcmtk::log4cplus::WARN_LOG_LEVEL); + } + /* the element could not be found in the dataset */ + else + checkElementValue(delem, tagKey, vm, type, result, moduleName, dcmtk::log4cplus::WARN_LOG_LEVEL); - return result; + return result; } - - -OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement &delem, - const IODRule* rule) +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem& dataset, DcmElement& delem, const IODRule* rule) { - if (rule == NULL) - return EC_CannotCheck; + if (rule == NULL) + return EC_CannotCheck; - return getAndCheckElementFromDataset(dataset, delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); + return getAndCheckElementFromDataset(dataset, delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); } - -OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, - DcmElement*& delem, - const IODRule* rule) +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem& dataset, DcmElement*& delem, const IODRule* rule) { - if (rule == NULL) - return EC_CannotCheck; + if (rule == NULL) + return EC_CannotCheck; - return getAndCheckElementFromDataset(dataset, rule->getTagKey(), delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); + return getAndCheckElementFromDataset( + dataset, rule->getTagKey(), delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); } - - -OFCondition DcmIODUtil::copyElementToDataset(OFCondition &result, - DcmItem &dataset, - const DcmElement &delem, - const IODRule* rule) +OFCondition +DcmIODUtil::copyElementToDataset(OFCondition& result, DcmItem& dataset, const DcmElement& delem, const IODRule* rule) { - if (rule == NULL) - return EC_CannotCheck; + if (rule == NULL) + return EC_CannotCheck; - if (result.bad()) - return result; + if (result.bad()) + return result; - // addElementToDataset() consumes element, so create a copy - DcmElement * copy = OFstatic_cast(DcmElement*, delem.clone()); - if (!copy) - return EC_MemoryExhausted; + // addElementToDataset() consumes element, so create a copy + DcmElement* copy = OFstatic_cast(DcmElement*, delem.clone()); + if (!copy) + return EC_MemoryExhausted; - return addElementToDataset(result, dataset, copy, rule); + return addElementToDataset(result, dataset, copy, rule); } - -OFCondition DcmIODUtil::copyElementToDataset(OFCondition &result, - DcmItem &dataset, - const DcmElement &delem, - const OFString &vm, - const OFString &type, - const char *moduleName) +OFCondition DcmIODUtil::copyElementToDataset(OFCondition& result, + DcmItem& dataset, + const DcmElement& delem, + const OFString& vm, + const OFString& type, + const char* moduleName) { - // Create temporary rule (in order to avoid code-copying) - IODRule rule(delem.getTag(), vm, type, moduleName, DcmIODTypes::IE_UNDEFINED); - return copyElementToDataset(result, dataset, delem, &rule); + // Create temporary rule (in order to avoid code-copying) + IODRule rule(delem.getTag(), vm, type, moduleName, DcmIODTypes::IE_UNDEFINED); + return copyElementToDataset(result, dataset, delem, &rule); } - -OFCondition DcmIODUtil::addElementToDataset(OFCondition &result, - DcmItem &dataset, - DcmElement *delem, - const IODRule* rule) +OFCondition +DcmIODUtil::addElementToDataset(OFCondition& result, DcmItem& dataset, DcmElement* delem, const IODRule* rule) { - OFBool insertionOK = OFFalse; - if (result.good()) - { - if (rule != NULL) + OFBool insertionOK = OFFalse; + if (result.good()) { - // Create empty type 2 element if required - OFString type = rule->getType(); - if (delem == NULL) - { - if (type == "2") - { - delem = DcmItem::newDicomElement(rule->getTagKey()); - if (delem == NULL) - { - result = EC_MemoryExhausted; - return result; - }; - } else if (type != "1") + if (rule != NULL) { - // Not type 1 or type 2 means the is type 1C, 2C or 3. For those it is - // fine to not insert anything - return EC_Normal; + // Create empty type 2 element if required + OFString type = rule->getType(); + if (delem == NULL) + { + if (type == "2") + { + delem = DcmItem::newDicomElement(rule->getTagKey()); + if (delem == NULL) + { + result = EC_MemoryExhausted; + return result; + }; + } + else if (type != "1") + { + // Not type 1 or type 2 means the is type 1C, 2C or 3. For those it is + // fine to not insert anything + return EC_Normal; + } + else + { + // type 1 is missing + DCMIOD_ERROR(DcmTag(rule->getTagKey()).getTagName() + << " " << rule->getTagKey() << " absent in " << rule->getModule() << " (type " + << rule->getType() << ")"); + result = IOD_EC_MissingAttribute; + return result; + } + } + // At this point, we certainly have an element. Check its value (empty ok for type 2) + if ((type == "2") || !delem->isEmpty()) + { + // Insert non-empty element or empty "type 2" element. First, perform the insertion, and then + // check the value. This is (at least) required for checking the character set of string values which + // relies on the element context, i.e. the surrounding item or dataset. + result = dataset.insert(delem, OFTrue /*replaceOld*/); + if (result.good()) + { + result = checkElementValue(*delem, + rule->getVM(), + type, + result, + rule->getModule().c_str(), + dcmtk::log4cplus::ERROR_LOG_LEVEL); + } + if (result.good()) + { + insertionOK = OFTrue; + } + // remove element if value is invalid + else + { + dataset.remove(delem); + } + } + else if (type == "1") + { + // Empty element value not allowed for "type 1" + result = EC_InvalidValue; + checkElementValue( + *delem, rule->getVM(), type, result, rule->getModule().c_str(), dcmtk::log4cplus::ERROR_LOG_LEVEL); + } } else { - // type 1 is missing - DCMIOD_ERROR(DcmTag(rule->getTagKey()).getTagName() << " " << rule->getTagKey() << " absent in " << rule->getModule() << " (type " << rule->getType() << ")"); - result = IOD_EC_MissingAttribute; - return result; + // No rule, no checks + result = EC_CannotCheck; } - } - // At this point, we certainly have an element. Check its value (empty ok for type 2) - if ((type == "2") || !delem->isEmpty()) - { - // Insert non-empty element or empty "type 2" element. First, perform the insertion, and then - // check the value. This is (at least) required for checking the character set of string values which - // relies on the element context, i.e. the surrounding item or dataset. - result = dataset.insert(delem, OFTrue /*replaceOld*/); - if (result.good()) - { - result = checkElementValue(*delem, rule->getVM(), type, result, rule->getModule().c_str(), dcmtk::log4cplus::ERROR_LOG_LEVEL); - } - if (result.good()) - { - insertionOK = OFTrue; - } - // remove element if value is invalid - else - { - dataset.remove(delem); - } - } - else if (type == "1") - { - // Empty element value not allowed for "type 1" - result = EC_InvalidValue; - checkElementValue(*delem, rule->getVM(), type, result, rule->getModule().c_str(), dcmtk::log4cplus::ERROR_LOG_LEVEL); - } } - else + if (!insertionOK) { - // No rule, no checks - result = EC_CannotCheck; + // Delete element since dataset did not take over ownership + delete delem; } - } - if (!insertionOK) - { - // Delete element since dataset did not take over ownership - delete delem; - } - return result; + return result; } - -const OFString& DcmIODUtil::currentDate(OFString &dateString) +const OFString& DcmIODUtil::currentDate(OFString& dateString) { - if (DcmDate::getCurrentDate(dateString).bad()) - { - dateString = ""; - } - return dateString; + if (DcmDate::getCurrentDate(dateString).bad()) + { + dateString = ""; + } + return dateString; } - -const OFString& DcmIODUtil::currentTime(OFString &timeString) +const OFString& DcmIODUtil::currentTime(OFString& timeString) { - if (DcmTime::getCurrentTime(timeString, OFTrue /*seconds*/, OFFalse /*fraction*/).bad()) - { - timeString = ""; - } - return timeString; + if (DcmTime::getCurrentTime(timeString, OFTrue /*seconds*/, OFFalse /*fraction*/).bad()) + { + timeString = ""; + } + return timeString; } - -OFCondition DcmIODUtil::checkElementValue(const DcmElement *delem, - const DcmTagKey &tagKey, - const OFString &vm, - const OFString &type, - const OFCondition &searchCond, - const char *moduleName, +OFCondition DcmIODUtil::checkElementValue(const DcmElement* delem, + const DcmTagKey& tagKey, + const OFString& vm, + const OFString& type, + const OFCondition& searchCond, + const char* moduleName, const dcmtk::log4cplus::LogLevel logLevel) { - OFCondition result = EC_Normal; - const OFString tagName = DcmTag(tagKey).getTagName(); - const OFString module = (moduleName == NULL) ? "IOD" : moduleName; - OFOStringStream error; - /* NB: type 1C and 2C cannot be checked, assuming to be optional */ - if (((type == "1") || (type == "2")) && searchCond.bad()) - { - error << tagName << " " << tagKey << " absent in " << module << " (type " << type << ")"; - result = IOD_EC_MissingAttribute; - } - else if ((delem == NULL) || OFconst_cast(DcmElement*, delem)->isEmpty(OFTrue /*normalize*/)) // cast away constness of delem; value modification can happen (eg. to remove padding) - { - /* however, type 1C should never be present with empty value */ - if (((type == "1") || (type == "1C")) && searchCond.good()) - { - error << tagName << " " << tagKey << " empty in " << module << " (type " << type << ")"; - result = EC_MissingValue; - } - } else { - result = OFconst_cast(DcmElement*, delem)->checkValue(vm, OFTrue /*oldFormat*/); // cast away constness of delem; value modification can happen (eg. to remove padding) - if (result == EC_InvalidCharacter) + OFCondition result = EC_Normal; + const OFString tagName = DcmTag(tagKey).getTagName(); + const OFString module = (moduleName == NULL) ? "IOD" : moduleName; + OFOStringStream error; + /* NB: type 1C and 2C cannot be checked, assuming to be optional */ + if (((type == "1") || (type == "2")) && searchCond.bad()) { - error << tagName << " " << tagKey << " contains invalid character(s) in " << module; + error << tagName << " " << tagKey << " absent in " << module << " (type " << type << ")"; + result = IOD_EC_MissingAttribute; } - else if (result == EC_ValueRepresentationViolated) + else if ((delem == NULL) + || OFconst_cast(DcmElement*, delem) + ->isEmpty(OFTrue /*normalize*/)) // cast away constness of delem; value modification can happen (eg. + // to remove padding) { - error << tagName << " " << tagKey << " violates VR definition in " << module; - } - else if (result == EC_ValueMultiplicityViolated) - { - const OFString vmText = (delem->getVR() == EVR_SQ) ? " #items" : " VM"; - error << tagName << " " << tagKey << vmText << " != " << vm << " in " << module; - } - else if (result == EC_MaximumLengthViolated) - { - error << tagName << " " << tagKey << " violates maximum VR length in " << module; + /* however, type 1C should never be present with empty value */ + if (((type == "1") || (type == "1C")) && searchCond.good()) + { + error << tagName << " " << tagKey << " empty in " << module << " (type " << type << ")"; + result = EC_MissingValue; + } } - else if (result.bad()) + else { - error << "INTERNAL ERROR while checking value of " << tagName << " " << tagKey << " in " << module; - result = EC_Normal; + result = OFconst_cast(DcmElement*, delem) + ->checkValue(vm, OFTrue /*oldFormat*/); // cast away constness of delem; value modification can + // happen (eg. to remove padding) + if (result == EC_InvalidCharacter) + { + error << tagName << " " << tagKey << " contains invalid character(s) in " << module; + } + else if (result == EC_ValueRepresentationViolated) + { + error << tagName << " " << tagKey << " violates VR definition in " << module; + } + else if (result == EC_ValueMultiplicityViolated) + { + const OFString vmText = (delem->getVR() == EVR_SQ) ? " #items" : " VM"; + error << tagName << " " << tagKey << vmText << " != " << vm << " in " << module; + } + else if (result == EC_MaximumLengthViolated) + { + error << tagName << " " << tagKey << " violates maximum VR length in " << module; + } + else if (result.bad()) + { + error << "INTERNAL ERROR while checking value of " << tagName << " " << tagKey << " in " << module; + result = EC_Normal; + } } - } - OFSTRINGSTREAM_GETSTR(error, tmpString) - if (strlen(tmpString) > 0) - { - switch (logLevel) + OFSTRINGSTREAM_GETSTR(error, tmpString) + if (strlen(tmpString) > 0) { - case dcmtk::log4cplus::TRACE_LOG_LEVEL: DCMIOD_TRACE(tmpString); break; - case dcmtk::log4cplus::DEBUG_LOG_LEVEL: DCMIOD_DEBUG(tmpString); break; - case dcmtk::log4cplus::WARN_LOG_LEVEL : DCMIOD_WARN(tmpString); break; - case dcmtk::log4cplus::INFO_LOG_LEVEL : DCMIOD_INFO(tmpString); break; - case dcmtk::log4cplus::ERROR_LOG_LEVEL : DCMIOD_ERROR(tmpString); break; - case dcmtk::log4cplus::FATAL_LOG_LEVEL: DCMIOD_FATAL(tmpString); break; - default: DCMIOD_WARN(tmpString);; + switch (logLevel) + { + case dcmtk::log4cplus::TRACE_LOG_LEVEL: + DCMIOD_TRACE(tmpString); + break; + case dcmtk::log4cplus::DEBUG_LOG_LEVEL: + DCMIOD_DEBUG(tmpString); + break; + case dcmtk::log4cplus::WARN_LOG_LEVEL: + DCMIOD_WARN(tmpString); + break; + case dcmtk::log4cplus::INFO_LOG_LEVEL: + DCMIOD_INFO(tmpString); + break; + case dcmtk::log4cplus::ERROR_LOG_LEVEL: + DCMIOD_ERROR(tmpString); + break; + case dcmtk::log4cplus::FATAL_LOG_LEVEL: + DCMIOD_FATAL(tmpString); + break; + default: + DCMIOD_WARN(tmpString); + ; + } } - } - OFSTRINGSTREAM_FREESTR(tmpString) - return result; + OFSTRINGSTREAM_FREESTR(tmpString) + return result; } - -OFCondition DcmIODUtil::checkElementValue(const DcmElement &delem, - const OFString &vm, - const OFString &type, - const OFCondition &searchCond, - const char *moduleName, +OFCondition DcmIODUtil::checkElementValue(const DcmElement& delem, + const OFString& vm, + const OFString& type, + const OFCondition& searchCond, + const char* moduleName, const dcmtk::log4cplus::LogLevel logLevel) { - /* call the real function */ - return checkElementValue(&delem, delem.getTag(), vm, type, searchCond, moduleName, logLevel); + /* call the real function */ + return checkElementValue(&delem, delem.getTag(), vm, type, searchCond, moduleName, logLevel); } - -OFCondition DcmIODUtil::getStringValueFromElement(const DcmElement &delem, - OFString &stringValue, - const signed long pos) +OFCondition DcmIODUtil::getStringValueFromElement(const DcmElement& delem, OFString& stringValue, const signed long pos) { - OFCondition result = EC_Normal; - // cast away constness of delem; value modification can happen (eg. to remove padding) - if (pos < 0) - result = OFconst_cast(DcmElement &, delem).getOFStringArray(stringValue); - else - result = OFconst_cast(DcmElement &, delem).getOFString(stringValue, OFstatic_cast(unsigned long, pos)); - if (result.bad()) - stringValue.clear(); - return result; + OFCondition result = EC_Normal; + // cast away constness of delem; value modification can happen (eg. to remove padding) + if (pos < 0) + result = OFconst_cast(DcmElement&, delem).getOFStringArray(stringValue); + else + result = OFconst_cast(DcmElement&, delem).getOFString(stringValue, OFstatic_cast(unsigned long, pos)); + if (result.bad()) + stringValue.clear(); + return result; } - -OFCondition DcmIODUtil::getFloat64ValueFromElement(const DcmElement& delem, - Float64& result, - const unsigned long pos) +OFCondition DcmIODUtil::getFloat64ValueFromElement(const DcmElement& delem, Float64& result, const unsigned long pos) { - return OFconst_cast(DcmElement &, delem).getFloat64(result, OFstatic_cast(unsigned long, pos)); + return OFconst_cast(DcmElement&, delem).getFloat64(result, OFstatic_cast(unsigned long, pos)); } - -OFCondition DcmIODUtil::getFloat64ValuesFromElement(const DcmElement& delem, - OFVector& result) +OFCondition DcmIODUtil::getFloat64ValuesFromElement(const DcmElement& delem, OFVector& result) { - Float64* floats = NULL; - OFCondition cond = OFconst_cast(DcmElement &, delem).getFloat64Array(floats); - if (cond.good()) - { - size_t vm = OFconst_cast(DcmElement &, delem).getNumberOfValues(); - for (size_t n = 0; n < vm; n++) + Float64* floats = NULL; + OFCondition cond = OFconst_cast(DcmElement&, delem).getFloat64Array(floats); + if (cond.good()) { - result.push_back(floats[n]); + size_t vm = OFconst_cast(DcmElement&, delem).getNumberOfValues(); + for (size_t n = 0; n < vm; n++) + { + result.push_back(floats[n]); + } } - } - return cond; + return cond; } - -OFCondition DcmIODUtil::getStringValueFromItem(const DcmTagKey& key, - DcmItem& item, - OFString& result, - const signed long& pos) +OFCondition +DcmIODUtil::getStringValueFromItem(const DcmTagKey& key, DcmItem& item, OFString& result, const signed long& pos) { - DcmElement *elem = NULL; - item.findAndGetElement(key, elem); - if (elem != NULL) - return DcmIODUtil::getStringValueFromElement(*elem, result, pos); - else - return EC_TagNotFound; + DcmElement* elem = NULL; + item.findAndGetElement(key, elem); + if (elem != NULL) + return DcmIODUtil::getStringValueFromElement(*elem, result, pos); + else + return EC_TagNotFound; } +OFCondition +DcmIODUtil::getFloat64ValueFromItem(const DcmTagKey& key, DcmItem& item, Float64& result, const unsigned long& pos) +{ + DcmElement* elem = NULL; + OFCondition cond = item.findAndGetElement(key, elem); + if (elem != NULL) + { + cond = DcmIODUtil::getFloat64ValueFromElement(*elem, result, pos); + } + return cond; +} -OFCondition DcmIODUtil::getFloat64ValueFromItem(const DcmTagKey& key, - DcmItem& item, - Float64& result, - const unsigned long& pos) +OFCondition DcmIODUtil::getFloat64ValuesFromItem(const DcmTagKey& key, DcmItem& item, OFVector& result) { - DcmElement *elem = NULL; - OFCondition cond = item.findAndGetElement(key, elem); - if (elem != NULL) - { - cond = DcmIODUtil::getFloat64ValueFromElement(*elem, result, pos); - } - return cond; + DcmElement* elem = NULL; + OFCondition cond = item.findAndGetElement(key, elem); + if (elem != NULL) + { + cond = DcmIODUtil::getFloat64ValuesFromElement(*elem, result); + } + return cond; } +OFCondition DcmIODUtil::setFloat64ValuesOnElement(DcmElement& delem, + const OFVector& values, + const OFString& vm, + const OFBool check) +{ + OFCondition result; + if (values.size() > OFnumeric_limits::max()) + { + DCMIOD_ERROR("Too many values provided (" << values.size() << " for element: " << delem.getTag().getXTag()); + return IOD_EC_InvalidElementValue; + } + const unsigned long vmCount = OFstatic_cast(unsigned long, values.size()); + OFVector::const_iterator it = values.begin(); + for (unsigned long count = 0; count < vmCount; count++) + { + result = delem.putFloat64((*it), count); + if (result.bad()) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Setting value " + << " #" << count << " to \" " << *it << "\" not possible"); + } + else if (check) + { + result = DcmElement::checkVM(vmCount, vm); + } + it++; + } + return result; +} -OFCondition DcmIODUtil::getFloat64ValuesFromItem(const DcmTagKey& key, - DcmItem& item, - OFVector& result) +OFCondition DcmIODUtil::getFloat32ValueFromElement(const DcmElement& delem, Float32& result, const unsigned long pos) { - DcmElement *elem = NULL; - OFCondition cond = item.findAndGetElement(key, elem); - if (elem != NULL) - { - cond = DcmIODUtil::getFloat64ValuesFromElement(*elem, result); - } - return cond; + return OFconst_cast(DcmElement&, delem).getFloat32(result, OFstatic_cast(unsigned long, pos)); } +OFCondition DcmIODUtil::setFloat32ValuesOnElement(DcmElement& delem, + const OFVector& values, + const OFString& vm, + const OFBool check) +{ + OFCondition result; + if (values.size() > OFnumeric_limits::max()) + { + DCMIOD_ERROR("Too many values provided (" << values.size() << " for element: " << delem.getTag().getXTag()); + return IOD_EC_InvalidElementValue; + } + const unsigned long vmCount = OFstatic_cast(unsigned long, values.size()); + OFVector::const_iterator it = values.begin(); + for (unsigned long count = 0; count < vmCount; count++) + { + result = delem.putFloat32((*it), count); + if (result.bad()) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Setting value " + << " #" << count << " to \" " << *it << "\" not possible"); + } + else if (check) + { + result = DcmElement::checkVM(vmCount, vm); + } + it++; + } + return result; +} -OFCondition DcmIODUtil::setUint16ValuesOnElement(DcmElement &delem, +OFCondition DcmIODUtil::setUint16ValuesOnElement(DcmElement& delem, const OFVector& values, const OFString& vm, const OFBool check) { - OFCondition result; - OFVector::const_iterator it = values.begin(); - for (size_t count=0; count < values.size(); count++ ) - { - result = delem.putUint16( (*it) ); - if ( result.bad() ) + OFCondition result; + if (values.size() > OFnumeric_limits::max()) { - DCMIOD_WARN(delem.getTag().getXTag() << ": Setting value " << " #" << count << " to \" " << *it << "\" not possible"); + DCMIOD_ERROR("Too many values provided (" << values.size() << " for element: " << delem.getTag().getXTag()); + return IOD_EC_InvalidElementValue; } - else if (check) + const unsigned long vmCount = OFstatic_cast(unsigned long, values.size()); + OFVector::const_iterator it = values.begin(); + for (unsigned long count = 0; count < vmCount; count++) { - result = DcmElement::checkVM(OFstatic_cast(unsigned long, values.size()), vm); + result = delem.putUint16((*it), count); + if (result.bad()) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Setting value " + << " #" << count << " to \" " << *it << "\" not possible"); + } + else if (check) + { + result = DcmElement::checkVM(vmCount, vm); + } + it++; } - it++; - } - return result; + return result; } - -OFCondition DcmIODUtil::getUint16ValuesFromElement(DcmElement &delem, - OFVector& values) +OFCondition DcmIODUtil::getUint16ValuesFromElement(DcmElement& delem, OFVector& values) { - OFCondition result; - const size_t count = delem.getNumberOfValues(); - values.reserve(count); - for (size_t i = 0; i < count; i++) - { - Uint16 val; - result = delem.getUint16(val, OFstatic_cast(unsigned long, i)); - if (result.bad()) + OFCondition result; + const size_t count = delem.getNumberOfValues(); + values.reserve(count); + for (size_t i = 0; i < count; i++) { - DCMIOD_WARN(delem.getTag().getXTag() << ": Getting value " << " #" << i << " not possible"); - break; + Uint16 val; + result = delem.getUint16(val, OFstatic_cast(unsigned long, i)); + if (result.bad()) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Getting value " + << " #" << i << " not possible"); + break; + } + values.push_back(val); } - values.push_back(val); - } - return result; + return result; } - void DcmIODUtil::checkSubSequence(OFCondition& result, DcmItem& surroundingItem, const DcmTagKey& seqKey, @@ -466,152 +537,230 @@ void DcmIODUtil::checkSubSequence(OFCondition& result, const OFString& module, const dcmtk::log4cplus::LogLevel logLevel) { - OFCondition exists = EC_Normal; - /* check result */ - if ( result.good() ) - { - DcmSequenceOfItems *seq = NULL; - exists = surroundingItem.findAndGetSequence(seqKey, seq); - result = DcmIODUtil::checkElementValue(seq, seqKey, cardinality, type, exists, module.c_str(), logLevel); - } -} - - -OFCondition DcmIODUtil::getAndCheckSingleItem(DcmSequenceOfItems& seq, - DcmItem*& item, - const DcmTagKey& checkKey) -{ - item = NULL; - const OFString tagName = OFconst_cast(DcmTag*, &seq.getTag())->getTagName(); // getTagName is not const... - if (checkKey != DCM_UndefinedTagKey) - { - if (seq.getTag().getXTag() != checkKey) - { - DCMIOD_ERROR("Expected sequence " << checkKey << " but got " << &seq.getTag() << "(" << tagName << ")"); - return EC_ItemNotFound; - } - } - - // get actual tag name and cardinality - const unsigned long card = seq.card(); - if (card != 1) - { - if (card > 1) - { - DCMIOD_WARN("Only single item allowed in " << tagName << ", ignoring " << card -1 << " other items"); - } - else // card = 0 - { - DCMIOD_WARN("Cannot read from sequence " << tagName << ": No item found"); - return EC_ItemNotFound; - } - } - // get item and return it - item = seq.getItem(0); - if (item == NULL) - { - DCMIOD_ERROR("Cannot read item from " << tagName << ": No item found (internal error)"); - return EC_CorruptedData; - } - return EC_Normal; -} - - -OFCondition DcmIODUtil::checkSOPClass(DcmItem* item, - const OFString& desiredSOPClass, - OFString& valueFound) -{ - valueFound.clear(); - if ( (item == NULL) || (item->card() == 0) ) - { - DCMIOD_TRACE("Cannot check SOP Class UID: Dataset not present or empty"); - return EC_IllegalParameter; - } - OFCondition result = item->findAndGetOFString(DCM_SOPClassUID, valueFound); - if ( result.bad() ) - { - DCMIOD_TRACE("No SOP Class UID in file, giving up"); - return EC_TagNotFound; - } - if (valueFound != desiredSOPClass) - { - DCMIOD_TRACE("File is not of SOP Class " << desiredSOPClass << ", but instead SOP Class is " << dcmFindNameOfUID(valueFound.c_str(), valueFound.c_str()) ); - return EC_InvalidValue; - } - return EC_Normal; -} - - -OFBool DcmIODUtil::isSequenceTag(const DcmTagKey& key, - const OFString& privateCreator) -{ - const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); - const DcmDictEntry *dictRef = NULL; - if (privateCreator.empty()) - dictRef = globalDataDict.findEntry(key, NULL); - else - dictRef = globalDataDict.findEntry(key, privateCreator.c_str()); - DcmVR vr; - if (dictRef) - { - vr = dictRef->getVR(); - } - dcmDataDict.rdunlock(); - if (vr.getEVR() == EVR_SQ) - return OFTrue; - return OFFalse; + OFCondition exists = EC_Normal; + /* check result */ + if (result.good()) + { + DcmSequenceOfItems* seq = NULL; + exists = surroundingItem.findAndGetSequence(seqKey, seq); + result = DcmIODUtil::checkElementValue(seq, seqKey, cardinality, type, exists, module.c_str(), logLevel); + } } +OFCondition DcmIODUtil::getAndCheckSingleItem(DcmSequenceOfItems& seq, DcmItem*& item, const DcmTagKey& checkKey) +{ + item = NULL; + const OFString tagName = OFconst_cast(DcmTag*, &seq.getTag())->getTagName(); // getTagName is not const... + if (checkKey != DCM_UndefinedTagKey) + { + if (seq.getTag().getXTag() != checkKey) + { + DCMIOD_ERROR("Expected sequence " << checkKey << " but got " << &seq.getTag() << "(" << tagName << ")"); + return EC_ItemNotFound; + } + } -const DcmTagKey DcmIODUtil::parseTagKey(const OFString& keyString) + // get actual tag name and cardinality + const unsigned long card = seq.card(); + if (card != 1) + { + if (card > 1) + { + DCMIOD_WARN("Only single item allowed in " << tagName << ", ignoring " << card - 1 << " other items"); + } + else // card = 0 + { + DCMIOD_WARN("Cannot read from sequence " << tagName << ": No item found"); + return EC_ItemNotFound; + } + } + // get item and return it + item = seq.getItem(0); + if (item == NULL) + { + DCMIOD_ERROR("Cannot read item from " << tagName << ": No item found (internal error)"); + return EC_CorruptedData; + } + return EC_Normal; +} + +OFCondition DcmIODUtil::checkSOPClass(DcmItem* item, const OFString& desiredSOPClass, OFString& valueFound) { - unsigned int g, e; - DcmTagKey resultKey = DCM_UndefinedTagKey; - if (sscanf(keyString.c_str(), "(%x,%x)", &g, &e) == 2) - { - resultKey.set(OFstatic_cast(Uint16, g), OFstatic_cast(Uint16, e)); - } - return resultKey; + valueFound.clear(); + if ((item == NULL) || (item->card() == 0)) + { + DCMIOD_TRACE("Cannot check SOP Class UID: Dataset not present or empty"); + return EC_IllegalParameter; + } + OFCondition result = item->findAndGetOFString(DCM_SOPClassUID, valueFound); + if (result.bad()) + { + DCMIOD_TRACE("No SOP Class UID in file, giving up"); + return EC_TagNotFound; + } + if (valueFound != desiredSOPClass) + { + DCMIOD_TRACE("File is not of SOP Class " << desiredSOPClass << ", but instead SOP Class is " + << dcmFindNameOfUID(valueFound.c_str(), valueFound.c_str())); + return EC_InvalidValue; + } + return EC_Normal; } +OFBool DcmIODUtil::isSequenceTag(const DcmTagKey& key, const OFString& privateCreator) +{ + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry* dictRef = NULL; + if (privateCreator.empty()) + dictRef = globalDataDict.findEntry(key, NULL); + else + dictRef = globalDataDict.findEntry(key, privateCreator.c_str()); + DcmVR vr; + if (dictRef) + { + vr = dictRef->getVR(); + } + dcmDataDict.rdunlock(); + if (vr.getEVR() == EVR_SQ) + return OFTrue; + return OFFalse; +} + +const DcmTagKey DcmIODUtil::parseTagKey(const OFString& keyString) +{ + unsigned int g, e; + DcmTagKey resultKey = DCM_UndefinedTagKey; + if (sscanf(keyString.c_str(), "(%x,%x)", &g, &e) == 2) + { + resultKey.set(OFstatic_cast(Uint16, g), OFstatic_cast(Uint16, e)); + } + return resultKey; +} OFCondition DcmIODUtil::decompress(DcmDataset& dset) { - DcmXfer xfer = dset.getOriginalXfer(); - if (xfer.isEncapsulated()) - { - if (EC_Normal != dset.chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + DcmXfer xfer = dset.getOriginalXfer(); + if (xfer.isEncapsulated()) { - DCMIOD_ERROR("No conversion to uncompressed transfer syntax possible!"); - return IOD_EC_CannotDecompress; + if (EC_Normal != dset.chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + { + + DCMIOD_ERROR("No conversion from " << xfer.getXferName() << " to uncompressed transfer syntax possible!"); + return IOD_EC_CannotDecompress; + } } - } - return EC_Normal; + return EC_Normal; } - OFString DcmIODUtil::createUID(const Uint8 level) { - char uid[100]; - switch (level) - { - case 0: dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); break; - case 1: dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); break; - case 2: dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); break; - default: dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); - } - return uid; + char uid[100]; + switch (level) + { + case 0: + dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); + break; + case 1: + dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); + break; + case 2: + dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); + break; + default: + dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); + } + return uid; +} + +Uint32 DcmIODUtil::limitMaxFrames(const size_t numFramesPresent, const OFString& warning) +{ + if (numFramesPresent > 2147483647) + { + DCMIOD_WARN(warning); + return 2147483647; + } + return OFstatic_cast(Uint16, numFramesPresent); } +OFCondition DcmIODUtil::extractBinaryFrames(Uint8* pixData, + const size_t numFrames, + const size_t bitsPerFrame, + OFVector& results) +{ + // Will hold the bit position (0-7) that the current frame starts from. The + // first frame will always start at bit 0. + Uint8 bitShift = 0; + // Compute length in bytes we need to consider for each frame. + size_t frameLengthBytes = bitsPerFrame / 8; + // If the number of bits is not dividable by 8, we need part of an extra + // byte in the end. Since we like to set the unused bits to 0 in such a last + // byte to 0, remember the number. + size_t overlapBits = (8 - (bitsPerFrame % 8)) % 8; + // Add an extra byte if we we fill a partial byte in the end + if (overlapBits != 0) + frameLengthBytes++; + // Points to current reading position within pixData + Uint8* readPos = pixData; + // Loop over each frame and copy it to Frame structures + for (size_t f = 0; f < numFrames; f++) + { + // Create frame with correct length and copy 1:1 from pixel data + DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); + frame->length = frameLengthBytes; + frame->pixData = new Uint8[frameLengthBytes]; + if (!frame->pixData) + { + delete frame; + return EC_MemoryExhausted; + } + memcpy(frame->pixData, readPos, frame->length); + // If we have been copying too much, i.e the first bits of the frame + // actually belong to the former frame, shift the whole frame this amount + // of bits to the left in order to shift the superfluous bits out, i.e. + // make frame start at byte boundary. + if (bitShift > 0) + { + DcmIODUtil::alignFrameOnByteBoundary(frame->pixData, frame->length, 8 - bitShift); + } + // Adapt last byte by masking out unused bits (i.e. those belonging to next frame). + // A reader should ignore those unused bits anyway. + frame->pixData[frame->length - 1] = (frame->pixData[frame->length - 1] << (overlapBits)) >> (overlapBits); + // Store frame + results.push_back(frame); + // Compute the bitshift created by this frame + bitShift = (8 - ((f + 1) * bitsPerFrame) % 8) % 8; + // If the previous byte read has not been used completely, i.e. it contains + // also bytes of the next frame, rewind read position to the previous byte + // that was partially read. Otherwise skip to the next full byte. + if (bitShift > 0) + { + readPos = readPos + frame->length - 1; + } + else + { + readPos = readPos + frame->length; + } + } + return EC_Normal; +} -Uint32 DcmIODUtil::limitMaxFrames(const size_t numFramesPresent, - const OFString& warning) +void DcmIODUtil::alignFrameOnByteBoundary(Uint8* buf, size_t bufLen, Uint8 numBits) { - if (numFramesPresent > 2147483647) - { - DCMIOD_WARN(warning); - return 2147483647; - } - return OFstatic_cast(Uint16, numFramesPresent); + if (numBits > 7) + { + DCMIOD_ERROR("Invalid input data: alignFrameOnByteBoundary() can only shift 0-7 bits"); + return; + } + for (size_t x = 0; x < bufLen - 1; x++) + { + // Shift current byte + buf[x] = buf[x] >> numBits; + // isolate portion of next byte that must be shifted into current byte + Uint8 next = (buf[x + 1] << (8 - numBits)); + // Take over portion from next byte + buf[x] |= next; + } + // Shift last byte manually + buf[bufLen - 1] >>= numBits; } diff --git a/dcmiod/libsrc/modacquisitioncontext.cc b/dcmiod/libsrc/modacquisitioncontext.cc index ceedbb2f..0796b900 100644 --- a/dcmiod/libsrc/modacquisitioncontext.cc +++ b/dcmiod/libsrc/modacquisitioncontext.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,49 +19,42 @@ * */ - -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modacquisitioncontext.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODAcquisitionContextModule::m_ModuleName = "AcquisitionContextModule"; - -IODAcquisitionContextModule::IODAcquisitionContextModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODAcquisitionContextModule::IODAcquisitionContextModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODAcquisitionContextModule::IODAcquisitionContextModule() -: IODModule() + : IODModule() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODAcquisitionContextModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODAcquisitionContextModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_AcquisitionContextSequence, "1-n","2", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_AcquisitionContextSequence, "1-n", "2", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - IODAcquisitionContextModule::~IODAcquisitionContextModule() { } - // --- get attributes (C++ string) --- // --- set attributes --- diff --git a/dcmiod/libsrc/modbase.cc b/dcmiod/libsrc/modbase.cc index 9ecde195..03528bca 100644 --- a/dcmiod/libsrc/modbase.cc +++ b/dcmiod/libsrc/modbase.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,273 +19,250 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcitem.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmiod/iodrules.h" -#include "dcmtk/dcmdata/dcdeftag.h" - +#include "dcmtk/dcmiod/iodutil.h" IODComponent::IODComponent(const IODComponent& rhs) -: m_Item(OFstatic_cast(DcmItem*, rhs.m_Item->clone())) -, m_Rules(rhs.m_Rules->clone()) -, m_Parent(OFnullptr) + : m_Item(OFstatic_cast(DcmItem*, rhs.m_Item->clone())) + , m_Rules(rhs.m_Rules->clone()) + , m_Parent(OFnullptr) { - } - -IODComponent::IODComponent(OFshared_ptr item, - OFshared_ptr rules, - IODComponent* parent) -: m_Item(item), - m_Rules(rules), - m_Parent(parent) +IODComponent::IODComponent(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent) + : m_Item(item) + , m_Rules(rules) + , m_Parent(parent) { - if (!m_Item) - m_Item.reset(new DcmItem()); + if (!m_Item) + m_Item.reset(new DcmItem()); - if (!m_Rules) - m_Rules.reset(new IODRules()); + if (!m_Rules) + m_Rules.reset(new IODRules()); } - IODComponent::IODComponent(IODComponent* parent) -: m_Item(), - m_Rules(), - m_Parent(parent) + : m_Item() + , m_Rules() + , m_Parent(parent) { - m_Item.reset(new DcmItem()); - m_Rules.reset(new IODRules()); + m_Item.reset(new DcmItem()); + m_Rules.reset(new IODRules()); } - IODComponent::~IODComponent() { - // Nothing to do for shared pointers + // Nothing to do for shared pointers } - IODComponent& IODComponent::operator=(const IODComponent& rhs) { - if (&rhs != this) - { - m_Item.reset(OFstatic_cast(DcmItem*, rhs.m_Item->clone())); - m_Rules.reset(rhs.m_Rules->clone()); - m_Parent = OFnullptr; - } - return *this; + if (&rhs != this) + { + m_Item.reset(OFstatic_cast(DcmItem*, rhs.m_Item->clone())); + m_Rules.reset(rhs.m_Rules->clone()); + m_Parent = OFnullptr; + } + return *this; } - void IODComponent::inventMissing() { - // Try to fill in missing type 1 information - OFVector writeRules = m_Rules->getByModule(getName()); - OFVector::iterator rule = writeRules.begin(); - while (rule != writeRules.end()) - { - OFString val = (*rule)->getDefaultValue() ; - // We have a default value - if ( val.length() != 0 ) + // Try to fill in missing type 1 information + OFVector writeRules = m_Rules->getByModule(getName()); + OFVector::iterator rule = writeRules.begin(); + while (rule != writeRules.end()) { - // Check if element is not set - DcmElement *elem = NULL; - if ( getData().findAndGetElement( (*rule)->getTagKey(), elem ).bad() ) - { - elem = DcmItem::newDicomElement((*rule)->getTagKey()); - if (elem == NULL) - { - DCMIOD_ERROR("Could not allocate element " << (*rule)->getTagKey()); - } - else + OFString val = (*rule)->getDefaultValue(); + // We have a default value + if (val.length() != 0) { - elem->putString(val.c_str()); - m_Item->insert(elem); + // Check if element is not set + DcmElement* elem = NULL; + if (getData().findAndGetElement((*rule)->getTagKey(), elem).bad()) + { + elem = DcmItem::newDicomElement((*rule)->getTagKey()); + if (elem == NULL) + { + DCMIOD_ERROR("Could not allocate element " << (*rule)->getTagKey()); + } + else + { + elem->putString(val.c_str()); + m_Item->insert(elem); + } + } + else if (elem->getLength() == 0) + { + elem->putString(val.c_str()); + } } - } - else if (elem->getLength() == 0) - { - elem->putString(val.c_str()); - } + rule++; } - rule++; - } } - void IODComponent::clearData() { - OFVector modRules = m_Rules->getByModule(getName()); - OFVector::iterator rule = modRules.begin(); - while (rule != modRules.end()) - { - m_Item->findAndDeleteElement( (*rule)->getTagKey() ); - rule++; - } + OFVector modRules = m_Rules->getByModule(getName()); + OFVector::iterator rule = modRules.begin(); + while (rule != modRules.end()) + { + m_Item->findAndDeleteElement((*rule)->getTagKey()); + rule++; + } } - void IODComponent::makeOptional() { - OFVector modRules = m_Rules->getByModule(getName()); - OFVector::iterator rule = modRules.begin(); - while (rule != modRules.end()) - { - (*rule)->setType("3"); - rule++; - } + OFVector modRules = m_Rules->getByModule(getName()); + OFVector::iterator rule = modRules.begin(); + while (rule != modRules.end()) + { + (*rule)->setType("3"); + rule++; + } } - -OFCondition IODComponent::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODComponent::read(DcmItem& source, const OFBool clearOldData) { - // Debug - DCMIOD_DEBUG("Reading component: " << getName()); + // Debug + DCMIOD_DEBUG("Reading component: " << getName()); - // Clear old data if desired - if (clearOldData) - { - clearData(); - } + // Clear old data if desired + if (clearOldData) + { + clearData(); + } - // Do actual reading - read(source, *m_Rules, *m_Item, getName()); - // We do not report errors here (only logger output) - return EC_Normal; + // Do actual reading + read(source, *m_Rules, *m_Item, getName()); + // We do not report errors here (only logger output) + return EC_Normal; } - OFCondition IODComponent::write(DcmItem& destination) { - // Debug - DCMIOD_DEBUG("Writing component: " << getName()); + // Debug + DCMIOD_DEBUG("Writing component: " << getName()); - // Invent missing values - inventMissing(); + // Invent missing values + inventMissing(); - // Start writing - OFCondition result = EC_Normal; - result = write(*m_Item, *m_Rules, destination, getName()); - return result; + // Start writing + OFCondition result = EC_Normal; + result = write(*m_Item, *m_Rules, destination, getName()); + return result; } - int IODComponent::compare(const IODComponent& rhs) const { - return this->m_Item.get()->compare( *(rhs.m_Item.get()) ) ; + return this->m_Item.get()->compare(*(rhs.m_Item.get())); } - OFCondition IODComponent::check(const OFBool quiet) { - OFCondition result; - IODRules::iterator it = m_Rules->begin(); - while (it != m_Rules->end()) - { - result = (*it).second->check(*m_Item, quiet); - if (result.bad()) - break; - else - it++; - } - return result; + OFCondition result; + IODRules::iterator it = m_Rules->begin(); + while (it != m_Rules->end()) + { + result = (*it).second->check(*m_Item, quiet); + if (result.bad()) + break; + else + it++; + } + return result; } - // static helper -OFCondition IODComponent::read(DcmItem& source, - IODRules& rules, - DcmItem& destination, - const OFString& componentName) +OFCondition IODComponent::read(DcmItem& source, IODRules& rules, DcmItem& destination, const OFString& componentName) { - OFVector modRules = rules.getByModule(componentName); - OFVector::iterator rule = modRules.begin(); - while (rule != modRules.end()) - { - // We do not read/copy sequences but only check them since they are not - // handled within this component - OFBool isSequence = ( DcmTag( (*rule)->getTagKey()).getEVR() == EVR_SQ); - if (isSequence) - { - DcmElement *elem = NULL; - OFCondition cond = source.findAndGetElement( (*rule)->getTagKey(), elem); - DcmIODUtil::checkElementValue(elem, (*rule)->getTagKey(), (*rule)->getVM(), (*rule)->getType(), cond, (*rule)->getModule().c_str(), dcmtk::log4cplus::WARN_LOG_LEVEL); - } - else // Normal attributes are checked and copied over into this IOD component + OFVector modRules = rules.getByModule(componentName); + OFVector::iterator rule = modRules.begin(); + while (rule != modRules.end()) { - DcmElement* elem = NULL; - DcmIODUtil::getAndCheckElementFromDataset(source, elem, *rule); - if (elem != NULL) - { - OFCondition result = destination.insert(elem, OFTrue); - if (result.bad()) + // We do not read/copy sequences but only check them since they are not + // handled within this component + OFBool isSequence = (DcmTag((*rule)->getTagKey()).getEVR() == EVR_SQ); + if (isSequence) + { + DcmElement* elem = NULL; + OFCondition cond = source.findAndGetElement((*rule)->getTagKey(), elem); + DcmIODUtil::checkElementValue(elem, + (*rule)->getTagKey(), + (*rule)->getVM(), + (*rule)->getType(), + cond, + (*rule)->getModule().c_str(), + dcmtk::log4cplus::WARN_LOG_LEVEL); + } + else // Normal attributes are checked and copied over into this IOD component { - DCMIOD_ERROR("Cannot insert element with tag: " << (*rule)->getTagKey()); - delete elem; + DcmElement* elem = NULL; + DcmIODUtil::getAndCheckElementFromDataset(source, elem, *rule); + if (elem != NULL) + { + OFCondition result = destination.insert(elem, OFTrue); + if (result.bad()) + { + DCMIOD_ERROR("Cannot insert element with tag: " << (*rule)->getTagKey()); + delete elem; + } + } } - } + rule++; } - rule++; - } - return EC_Normal; + return EC_Normal; } - // static helper -OFCondition IODComponent::write(DcmItem& source, - IODRules& rules, - DcmItem& destination, - const OFString& componentName) +OFCondition IODComponent::write(DcmItem& source, IODRules& rules, DcmItem& destination, const OFString& componentName) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - OFVector writeRules = rules.getByModule(componentName); - OFVector::iterator rule = writeRules.begin(); - while (rule != writeRules.end()) - { - DcmElement* elem = NULL; - source.findAndGetElement( (*rule)->getTagKey(), elem, OFFalse /* only this level */, OFTrue /* create copy*/); - DcmIODUtil::addElementToDataset(result, destination, elem, *rule); - rule++; - } + OFVector writeRules = rules.getByModule(componentName); + OFVector::iterator rule = writeRules.begin(); + while (rule != writeRules.end()) + { + DcmElement* elem = NULL; + source.findAndGetElement((*rule)->getTagKey(), elem, OFFalse /* only this level */, OFTrue /* create copy*/); + DcmIODUtil::addElementToDataset(result, destination, elem, *rule); + rule++; + } - return result; + return result; } - // -------- IODModule -------------- -IODModule::IODModule(): IODComponent() +IODModule::IODModule() + : IODComponent() { - // nothing to do, IODComponent does the work + // nothing to do, IODComponent does the work } - IODModule::IODModule(const IODModule& rhs) -: IODComponent(rhs.m_Item, rhs.m_Rules, rhs.m_Parent) + : IODComponent(rhs.m_Item, rhs.m_Rules, rhs.m_Parent) { - } - -IODModule::IODModule(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules) -: IODComponent(item, rules, NULL /* No parent for modules */) +IODModule::IODModule(OFshared_ptr item, OFshared_ptr rules) + : IODComponent(item, rules, NULL /* No parent for modules */) { - // nothing to do, IODComponent does the work + // nothing to do, IODComponent does the work } - IODModule& IODModule::operator=(const IODModule& rhs) { - if (this != &rhs) - { - m_Item = rhs.m_Item; - m_Rules = rhs.m_Rules; - m_Parent = rhs.m_Parent; - } - return *this; + if (this != &rhs) + { + m_Item = rhs.m_Item; + m_Rules = rhs.m_Rules; + m_Parent = rhs.m_Parent; + } + return *this; } diff --git a/dcmiod/libsrc/modcommoninstanceref.cc b/dcmiod/libsrc/modcommoninstanceref.cc index baeba898..69fa9602 100644 --- a/dcmiod/libsrc/modcommoninstanceref.cc +++ b/dcmiod/libsrc/modcommoninstanceref.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,339 +19,331 @@ * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/modcommoninstanceref.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/iodutil.h" // for static helpers const OFString IODCommonInstanceReferenceModule::m_ComponentName = "CommonInstanceReferenceModule"; -const OFString IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::m_ComponentName = "StudiesContainingOtherReferencedInstancesSequence"; - - -IODCommonInstanceReferenceModule::IODCommonInstanceReferenceModule(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules) -: IODModule(item, rules), - m_ReferenceSeriesItems(), - m_StudiesContainingOtherReferencedInstancesSequence() +const OFString IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::m_ComponentName + = "StudiesContainingOtherReferencedInstancesSequence"; + +IODCommonInstanceReferenceModule::IODCommonInstanceReferenceModule(OFshared_ptr item, + OFshared_ptr rules) + : IODModule(item, rules) + , m_ReferenceSeriesItems() + , m_StudiesContainingOtherReferencedInstancesSequence() { - resetRules(); + resetRules(); } - IODCommonInstanceReferenceModule::IODCommonInstanceReferenceModule() -: IODModule(), - m_ReferenceSeriesItems(), - m_StudiesContainingOtherReferencedInstancesSequence() + : IODModule() + , m_ReferenceSeriesItems() + , m_StudiesContainingOtherReferencedInstancesSequence() { - resetRules(); + resetRules(); } - IODCommonInstanceReferenceModule::~IODCommonInstanceReferenceModule() { - freeMemory(); + freeMemory(); } - OFString IODCommonInstanceReferenceModule::getName() const { - return m_ComponentName; + return m_ComponentName; } - -OFVector< IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* >& IODCommonInstanceReferenceModule::getReferencedSeriesItems() +OFVector& +IODCommonInstanceReferenceModule::getReferencedSeriesItems() { - return m_ReferenceSeriesItems; + return m_ReferenceSeriesItems; } - -OFVector & IODCommonInstanceReferenceModule::getStudiesContainingOtherReferences() +OFVector& +IODCommonInstanceReferenceModule::getStudiesContainingOtherReferences() { - return m_StudiesContainingOtherReferencedInstancesSequence; + return m_StudiesContainingOtherReferencedInstancesSequence; } - void IODCommonInstanceReferenceModule::clearData() { - freeMemory(); + freeMemory(); } - -OFCondition IODCommonInstanceReferenceModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODCommonInstanceReferenceModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - DcmIODUtil::readSubSequence(source, DCM_ReferencedSeriesSequence, m_ReferenceSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); - DcmIODUtil::readSubSequence(source, - DCM_StudiesContainingOtherReferencedInstancesSequence, - m_StudiesContainingOtherReferencedInstancesSequence, - m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); + DcmIODUtil::readSubSequence( + source, DCM_ReferencedSeriesSequence, m_ReferenceSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + DcmIODUtil::readSubSequence(source, + DCM_StudiesContainingOtherReferencedInstancesSequence, + m_StudiesContainingOtherReferencedInstancesSequence, + m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); - return EC_Normal; + return EC_Normal; } - OFCondition IODCommonInstanceReferenceModule::write(DcmItem& destination) { - OFCondition result = EC_Normal; - - DcmIODUtil::writeSubSequence >(result, DCM_ReferencedSeriesSequence, m_ReferenceSeriesItems, *m_Item, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); - DcmIODUtil::writeSubSequence >(result, - DCM_StudiesContainingOtherReferencedInstancesSequence, - m_StudiesContainingOtherReferencedInstancesSequence, - *m_Item, - m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); - if (result.good()) result = IODModule::write(destination); - return result; + OFCondition result = EC_Normal; + + DcmIODUtil::writeSubSequence >( + result, + DCM_ReferencedSeriesSequence, + m_ReferenceSeriesItems, + *m_Item, + m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + DcmIODUtil::writeSubSequence >( + result, + DCM_StudiesContainingOtherReferencedInstancesSequence, + m_StudiesContainingOtherReferencedInstancesSequence, + *m_Item, + m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); + if (result.good()) + result = IODModule::write(destination); + return result; } - -size_t IODCommonInstanceReferenceModule::addReferences( - const IODReferences& references, - const OFString& studyInstanceUID, - const OFBool clearOldData) +size_t IODCommonInstanceReferenceModule::addReferences(const IODReferences& references, + const OFString& studyInstanceUID, + const OFBool clearOldData) { - if (clearOldData) - { - clearData(); - } - OFString ourStudy = studyInstanceUID; - if (ourStudy.empty()) - { - m_Item->findAndGetOFString(DCM_StudyInstanceUID, ourStudy); - if (ourStudy.empty()) + if (clearOldData) { - DCMIOD_ERROR("Could not add references: No Study Instance UID specified for \"this\" object"); - return 0; + clearData(); } - } - - const OFVector refs = references.get(); - OFVector::const_iterator ref = refs.begin(); - size_t count = 0; - while (ref != refs.end()) - { - OFCondition result; - // If reference belongs into "this" study, add it to Referenced Series Sequence - OFString refStudy = (*ref)->m_StudyInstanceUID; - if ( refStudy == ourStudy ) + OFString ourStudy = studyInstanceUID; + if (ourStudy.empty()) { - result = addSeriesReference(m_ReferenceSeriesItems, **ref); + m_Item->findAndGetOFString(DCM_StudyInstanceUID, ourStudy); + if (ourStudy.empty()) + { + DCMIOD_ERROR("Could not add references: No Study Instance UID specified for \"this\" object"); + return 0; + } } - else + + const OFVector refs = references.get(); + OFVector::const_iterator ref = refs.begin(); + size_t count = 0; + while (ref != refs.end()) { - // Reference lies outside of "this" study, put it into Studies Containing - // Other Referenced Instances Sequence - OFVector::iterator it = m_StudiesContainingOtherReferencedInstancesSequence.begin(); - while (it != m_StudiesContainingOtherReferencedInstancesSequence.end()) - { - OFString studyEntry; - (*it)->getStudyInstanceUID(studyEntry); - if (studyEntry == refStudy) + OFCondition result; + // If reference belongs into "this" study, add it to Referenced Series Sequence + OFString refStudy = (*ref)->m_StudyInstanceUID; + if (refStudy == ourStudy) { - result = addSeriesReference( - (*it)->getReferencedSeriesAndInstanceReferences().getReferencedSeriesItems(), - **ref); - break; + result = addSeriesReference(m_ReferenceSeriesItems, **ref); } else { - it++; - } - } - // We did not find an entry for this study, add new one - if (it == m_StudiesContainingOtherReferencedInstancesSequence.end()) - { - StudiesOtherInstancesItem* newItem = new StudiesOtherInstancesItem(); - if (newItem) - { - result = newItem->setStudyInstanceUID(refStudy); - if (result.good()) - { - result = addSeriesReference(newItem->getReferencedSeriesAndInstanceReferences().getReferencedSeriesItems(), **ref); - } - if (result.good()) - { - m_StudiesContainingOtherReferencedInstancesSequence.push_back(newItem); - } - else - { - delete newItem; - } + // Reference lies outside of "this" study, put it into Studies Containing + // Other Referenced Instances Sequence + OFVector::iterator it + = m_StudiesContainingOtherReferencedInstancesSequence.begin(); + while (it != m_StudiesContainingOtherReferencedInstancesSequence.end()) + { + OFString studyEntry; + (*it)->getStudyInstanceUID(studyEntry); + if (studyEntry == refStudy) + { + result = addSeriesReference( + (*it)->getReferencedSeriesAndInstanceReferences().getReferencedSeriesItems(), **ref); + break; + } + else + { + it++; + } + } + // We did not find an entry for this study, add new one + if (it == m_StudiesContainingOtherReferencedInstancesSequence.end()) + { + StudiesOtherInstancesItem* newItem = new StudiesOtherInstancesItem(); + if (newItem) + { + result = newItem->setStudyInstanceUID(refStudy); + if (result.good()) + { + result = addSeriesReference( + newItem->getReferencedSeriesAndInstanceReferences().getReferencedSeriesItems(), **ref); + } + if (result.good()) + { + m_StudiesContainingOtherReferencedInstancesSequence.push_back(newItem); + } + else + { + delete newItem; + } + } + else + { + DCMIOD_ERROR("Memory exhausted while adding references to Common Instance Reference Module"); + return count; + } + } } - else + if (result.good()) { - DCMIOD_ERROR("Memory exhausted while adding references to Common Instance Reference Module"); - return count; + count++; } - } - } - if (result.good()) - { - count++; + ref++; } - ref++; - } - return count; + return count; } - void IODCommonInstanceReferenceModule::resetRules() { - // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level - m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_StudiesContainingOtherReferencedInstancesSequence, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule( + new IODRule( + DCM_StudiesContainingOtherReferencedInstancesSequence, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - OFCondition IODCommonInstanceReferenceModule::addSeriesReference( - OFVector& container, - const IODReference& ref) + OFVector& container, const IODReference& ref) { - OFCondition result; - OFVector::iterator series = container.begin(); - while ( series != container.end() ) - { - OFString s; - (*series)->getSeriesInstanceUID(s); - if (s == ref.m_SeriesInstanceUID) - { - // There is already an entry for this series - result = (*series)->addReference(ref.m_SOPClassUID, ref.m_SOPInstanceUID); - if (result.good()) - { - return EC_Normal; - } - else - { - DCMIOD_ERROR("Could not add reference to Common Instance Reference Module: " << ref.toString()); - return IOD_EC_InvalidElementValue; - } - } - series++; - } - // If we do not have such a series Referenced Series Sequence, add it - if (series == container.end()) - { - IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* newseries = new IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem(); - if (!newseries) - { - return EC_MemoryExhausted; - } - result = newseries->setSeriesInstanceUID( ref.m_SeriesInstanceUID); - if (result.good()) result = newseries->addReference(ref.m_SOPClassUID, ref.m_SOPInstanceUID); - if (result.good()) + OFCondition result; + OFVector::iterator series = container.begin(); + while (series != container.end()) { - container.push_back(newseries); + OFString s; + (*series)->getSeriesInstanceUID(s); + if (s == ref.m_SeriesInstanceUID) + { + // There is already an entry for this series + result = (*series)->addReference(ref.m_SOPClassUID, ref.m_SOPInstanceUID); + if (result.good()) + { + return EC_Normal; + } + else + { + DCMIOD_ERROR("Could not add reference to Common Instance Reference Module: " << ref.toString()); + return IOD_EC_InvalidElementValue; + } + } + series++; } - else + // If we do not have such a series Referenced Series Sequence, add it + if (series == container.end()) { - DCMIOD_ERROR("Could not add reference to Common Instance Reference Module: " << ref.toString()); + IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* newseries + = new IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem(); + if (!newseries) + { + return EC_MemoryExhausted; + } + result = newseries->setSeriesInstanceUID(ref.m_SeriesInstanceUID); + if (result.good()) + result = newseries->addReference(ref.m_SOPClassUID, ref.m_SOPInstanceUID); + if (result.good()) + { + container.push_back(newseries); + } + else + { + DCMIOD_ERROR("Could not add reference to Common Instance Reference Module: " << ref.toString()); + } } - } - return result; + return result; } - // -- IODCommonInstanceReferenceModule::StudiesOtherInstancesItem -- - -IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::StudiesOtherInstancesItem(OFshared_ptr< DcmItem > item, - OFshared_ptr< IODRules > rules, +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::StudiesOtherInstancesItem(OFshared_ptr item, + OFshared_ptr rules, IODComponent* parent) -: IODComponent(item, rules, parent), - m_ReferencedSeriesAndInstance() + : IODComponent(item, rules, parent) + , m_ReferencedSeriesAndInstance() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::StudiesOtherInstancesItem(IODComponent* parent) -: IODComponent(parent), - m_ReferencedSeriesAndInstance() + : IODComponent(parent) + , m_ReferencedSeriesAndInstance() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::~StudiesOtherInstancesItem() { - clearData(); + clearData(); } - - OFString IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getName() const { - return m_ComponentName; + return m_ComponentName; } - void IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::clearData() { - m_ReferencedSeriesAndInstance.clearData(); - IODComponent::clearData(); + m_ReferencedSeriesAndInstance.clearData(); + IODComponent::clearData(); } - OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - IODComponent::read(source, clearOldData); - m_ReferencedSeriesAndInstance.read(source, clearOldData); - return EC_Normal; + IODComponent::read(source, clearOldData); + m_ReferencedSeriesAndInstance.read(source, clearOldData); + return EC_Normal; } - OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::write(DcmItem& destination) { - OFCondition result = EC_Normal; - result = IODComponent::write(destination); + OFCondition result = EC_Normal; + result = IODComponent::write(destination); - if (result.good()) result = m_ReferencedSeriesAndInstance.write(destination); + if (result.good()) + result = m_ReferencedSeriesAndInstance.write(destination); - return result; + return result; } - void IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::resetRules() { - // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level - m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); } - -IODSeriesAndInstanceReferenceMacro& IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getReferencedSeriesAndInstanceReferences() +IODSeriesAndInstanceReferenceMacro& +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getReferencedSeriesAndInstanceReferences() { - return m_ReferencedSeriesAndInstance; + return m_ReferencedSeriesAndInstance; } - -OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getStudyInstanceUID(OFString& value, - const long signed int pos) const +OFCondition +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getStudyInstanceUID(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); } - OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::setStudyInstanceUID(const OFString& value, - const bool checkValue) + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID, value); + return result; } - void IODCommonInstanceReferenceModule::freeMemory() { - DcmIODUtil::freeContainer(m_StudiesContainingOtherReferencedInstancesSequence); - DcmIODUtil::freeContainer(m_ReferenceSeriesItems); + DcmIODUtil::freeContainer(m_StudiesContainingOtherReferencedInstancesSequence); + DcmIODUtil::freeContainer(m_ReferenceSeriesItems); } diff --git a/dcmiod/libsrc/modenhequipment.cc b/dcmiod/libsrc/modenhequipment.cc index 6c834cdb..33c7333a 100644 --- a/dcmiod/libsrc/modenhequipment.cc +++ b/dcmiod/libsrc/modenhequipment.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,143 +19,122 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modenhequipment.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcvrlo.h" -#include "dcmtk/dcmdata/dcvrst.h" #include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrst.h" #include "dcmtk/dcmiod/iodutil.h" -IODEnhGeneralEquipmentModule::IODEnhGeneralEquipmentModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_ModuleName("EnhancedGeneralEquipmentModule") +IODEnhGeneralEquipmentModule::IODEnhGeneralEquipmentModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_ModuleName("EnhancedGeneralEquipmentModule") { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODEnhGeneralEquipmentModule::IODEnhGeneralEquipmentModule() -: IODModule(), - m_ModuleName("EnhancedGeneralEquipmentModule") + : IODModule() + , m_ModuleName("EnhancedGeneralEquipmentModule") { - resetRules(); + resetRules(); } - OFCondition IODEnhGeneralEquipmentModule::create(const IODEnhGeneralEquipmentModule::EquipmentInfo& info, IODEnhGeneralEquipmentModule* equipment) { - equipment = new IODEnhGeneralEquipmentModule(); - if (!equipment) - { - return EC_MemoryExhausted; - } - return equipment->set(info); + equipment = new IODEnhGeneralEquipmentModule(); + if (!equipment) + { + return EC_MemoryExhausted; + } + return equipment->set(info); } - void IODEnhGeneralEquipmentModule::resetRules() { - m_Rules->addRule(new IODRule(DCM_Manufacturer, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_Manufacturer, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n", "1", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); } - IODEnhGeneralEquipmentModule::~IODEnhGeneralEquipmentModule() { - // Nothing to do + // Nothing to do } - OFString IODEnhGeneralEquipmentModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - -OFCondition IODEnhGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, - const long signed int pos) const +OFCondition IODEnhGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); } - -OFCondition IODEnhGeneralEquipmentModule::getManufacturer(OFString& value, - const long signed int pos) const +OFCondition IODEnhGeneralEquipmentModule::getManufacturer(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); } - -OFCondition IODEnhGeneralEquipmentModule::getManufacturerModelName(OFString& value, - const long signed int pos) const +OFCondition IODEnhGeneralEquipmentModule::getManufacturerModelName(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); } - -OFCondition IODEnhGeneralEquipmentModule::getSoftwareVersions(OFString& value, - const long signed int pos) const +OFCondition IODEnhGeneralEquipmentModule::getSoftwareVersions(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); } - -OFCondition IODEnhGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); + return result; } - -OFCondition IODEnhGeneralEquipmentModule::setManufacturer(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhGeneralEquipmentModule::setManufacturer(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); + return result; } - -OFCondition IODEnhGeneralEquipmentModule::setManufacturerModelName(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhGeneralEquipmentModule::setManufacturerModelName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); - return result; - + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); + return result; } - -OFCondition IODEnhGeneralEquipmentModule::setSoftwareVersions(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhGeneralEquipmentModule::setSoftwareVersions(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); + return result; } - OFCondition IODEnhGeneralEquipmentModule::set(const IODEnhGeneralEquipmentModule::EquipmentInfo& info) { - if (info.m_DeviceSerialNumber.empty() || info.m_Manufacturer.empty() || - info.m_ManufacturerModelName.empty() || info.m_SoftwareVersions.empty()) - return IOD_EC_InvalidElementValue; - - OFCondition result = setManufacturer(info.m_Manufacturer); - if (result.good()) result = setManufacturerModelName(info.m_ManufacturerModelName); - if (result.good()) result = setDeviceSerialNumber(info.m_DeviceSerialNumber); - if (result.good()) result = setSoftwareVersions(info.m_SoftwareVersions); - return result; + if (info.m_DeviceSerialNumber.empty() || info.m_Manufacturer.empty() || info.m_ManufacturerModelName.empty() + || info.m_SoftwareVersions.empty()) + return IOD_EC_InvalidElementValue; + + OFCondition result = setManufacturer(info.m_Manufacturer); + if (result.good()) + result = setManufacturerModelName(info.m_ManufacturerModelName); + if (result.good()) + result = setDeviceSerialNumber(info.m_DeviceSerialNumber); + if (result.good()) + result = setSoftwareVersions(info.m_SoftwareVersions); + return result; } diff --git a/dcmiod/libsrc/modenhusimage.cc b/dcmiod/libsrc/modenhusimage.cc index 7cb42a78..3aec0dab 100644 --- a/dcmiod/libsrc/modenhusimage.cc +++ b/dcmiod/libsrc/modenhusimage.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2020, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,652 +19,571 @@ * */ - -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modenhusimage.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODEnhUSImageModule::m_ModuleName = "EnhancedUSImageModule"; - -IODEnhUSImageModule::IODEnhUSImageModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_MandatoryViewAndSliceProgressionDirection(), - m_Anatomy("1" /* mandatory version */), - m_TransducerScanPattern(), - m_TransducerGeometry(), - m_TransducerBeamSteering(), - m_TransducerApplication() +IODEnhUSImageModule::IODEnhUSImageModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_MandatoryViewAndSliceProgressionDirection() + , m_Anatomy("1" /* mandatory version */) + , m_TransducerScanPattern() + , m_TransducerGeometry() + , m_TransducerBeamSteering() + , m_TransducerApplication() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODEnhUSImageModule::IODEnhUSImageModule() -: IODModule(), - m_MandatoryViewAndSliceProgressionDirection(), - m_Anatomy("1" /* mandatory version */), - m_TransducerScanPattern(), - m_TransducerGeometry(), - m_TransducerBeamSteering(), - m_TransducerApplication() + : IODModule() + , m_MandatoryViewAndSliceProgressionDirection() + , m_Anatomy("1" /* mandatory version */) + , m_TransducerScanPattern() + , m_TransducerGeometry() + , m_TransducerBeamSteering() + , m_TransducerApplication() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODEnhUSImageModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODEnhUSImageModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_ImageType, "4","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "1"), OFTrue); - m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "MONOCHROME2"), OFTrue); - m_Rules->addRule(new IODRule(DCM_Rows, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Columns, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsStored, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_HighBit, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "0"), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionDuration, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelSpacing, "2","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PositionMeasuringDeviceUsed, "1","1C" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1-n","1C" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n","1C" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "IDENTITY"), OFTrue); - m_Rules->addRule(new IODRule(DCM_RescaleSlope, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "1"), OFTrue); - m_Rules->addRule(new IODRule(DCM_RescaleIntercept, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "0"), OFTrue); - m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1","1" ,getName(), DcmIODTypes::IE_IMAGE, "NO"), OFTrue); - m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1","3" ,getName(), DcmIODTypes::IE_IMAGE, "NO"), OFTrue); - m_Rules->addRule(new IODRule(DCM_TransducerScanPatternCodeSequence, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_TransducerGeometryCodeSequence, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_TransducerBeamSteeringCodeSequence, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_TransducerApplicationCodeSequence, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ProcessingFunction, "1","3" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_MechanicalIndex, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BoneThermalIndex, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_CranialThermalIndex, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_SoftTissueThermalIndex, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DepthsOfFocus, "1-n","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DepthOfScanField, "1","1" ,getName(), DcmIODTypes::IE_IMAGE), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_ImageType, "4", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "1"), OFTrue); + m_Rules->addRule( + new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "MONOCHROME2"), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsStored, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_HighBit, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "0"), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDuration, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelSpacing, "2", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PositionMeasuringDeviceUsed, "1", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1-n", "1C", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n", "1C", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "IDENTITY"), + OFTrue); + m_Rules->addRule(new IODRule(DCM_RescaleSlope, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "1"), OFTrue); + m_Rules->addRule(new IODRule(DCM_RescaleIntercept, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "0"), OFTrue); + m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "NO"), OFTrue); + m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1", "3", getName(), DcmIODTypes::IE_IMAGE, "NO"), + OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerScanPatternCodeSequence, "1", "1", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerGeometryCodeSequence, "1", "1", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerBeamSteeringCodeSequence, "1", "1", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerApplicationCodeSequence, "1", "1", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_ProcessingFunction, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_MechanicalIndex, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BoneThermalIndex, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_CranialThermalIndex, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftTissueThermalIndex, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DepthsOfFocus, "1-n", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DepthOfScanField, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); } - IODEnhUSImageModule::~IODEnhUSImageModule() { - DcmIODUtil::freeContainer(m_TransducerBeamSteering); + DcmIODUtil::freeContainer(m_TransducerBeamSteering); } - -OFCondition IODEnhUSImageModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODEnhUSImageModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - { - DcmIODUtil::freeContainer(m_TransducerBeamSteering); - } - m_MandatoryViewAndSliceProgressionDirection.read(source, clearOldData); - m_Anatomy.read(source, clearOldData); - DcmIODUtil::readSingleItem(source, DCM_TransducerApplicationCodeSequence, m_TransducerApplication, m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); - DcmIODUtil::readSingleItem(source, DCM_TransducerGeometryCodeSequence, m_TransducerGeometry, m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); - DcmIODUtil::readSingleItem(source, DCM_TransducerScanPatternCodeSequence, m_TransducerGeometry, m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_TransducerBeamSteeringCodeSequence, m_TransducerBeamSteering, m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); - IODComponent::read(source, clearOldData); - return EC_Normal; + if (clearOldData) + { + DcmIODUtil::freeContainer(m_TransducerBeamSteering); + } + m_MandatoryViewAndSliceProgressionDirection.read(source, clearOldData); + m_Anatomy.read(source, clearOldData); + DcmIODUtil::readSingleItem(source, + DCM_TransducerApplicationCodeSequence, + m_TransducerApplication, + m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); + DcmIODUtil::readSingleItem(source, + DCM_TransducerGeometryCodeSequence, + m_TransducerGeometry, + m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); + DcmIODUtil::readSingleItem(source, + DCM_TransducerScanPatternCodeSequence, + m_TransducerScanPattern, + m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); + DcmIODUtil::readSubSequence(source, + DCM_TransducerBeamSteeringCodeSequence, + m_TransducerBeamSteering, + m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); + IODComponent::read(source, clearOldData); + return EC_Normal; } - - OFCondition IODEnhUSImageModule::write(DcmItem& destination) { - OFCondition result; + OFCondition result; - // Copy sequences to source (which then will be later copied to destination by IODComponent::write() - result = m_MandatoryViewAndSliceProgressionDirection.write(destination); - if (result.good()) result = m_Anatomy.write(destination); - DcmIODUtil::writeSingleItem(result, DCM_TransducerScanPatternCodeSequence, m_TransducerScanPattern, *m_Item, m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); - DcmIODUtil::writeSingleItem(result, DCM_TransducerGeometryCodeSequence, m_TransducerGeometry, *m_Item, m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); - DcmIODUtil::writeSingleItem(result, DCM_TransducerApplicationCodeSequence, m_TransducerApplication, *m_Item, m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); - DcmIODUtil::writeSubSequence(result, DCM_TransducerBeamSteeringCodeSequence, m_TransducerBeamSteering, *m_Item, m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); - if (result.good()) result = IODComponent::write(destination); - return result; + // Copy sequences to source (which then will be later copied to destination by IODComponent::write() + result = m_MandatoryViewAndSliceProgressionDirection.write(destination); + if (result.good()) + result = m_Anatomy.write(destination); + DcmIODUtil::writeSingleItem(result, + DCM_TransducerScanPatternCodeSequence, + m_TransducerScanPattern, + *m_Item, + m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); + DcmIODUtil::writeSingleItem(result, + DCM_TransducerGeometryCodeSequence, + m_TransducerGeometry, + *m_Item, + m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); + DcmIODUtil::writeSingleItem(result, + DCM_TransducerApplicationCodeSequence, + m_TransducerApplication, + *m_Item, + m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); + DcmIODUtil::writeSubSequence(result, + DCM_TransducerBeamSteeringCodeSequence, + m_TransducerBeamSteering, + *m_Item, + m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); + if (result.good()) + result = IODComponent::write(destination); + return result; } - // --- get attributes (C++ string) --- - -OFCondition IODEnhUSImageModule::getImageType(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getImageType(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); } - - -OFCondition IODEnhUSImageModule::getSamplesPerPixel(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getSamplesPerPixel(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); + return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); } - - -OFCondition IODEnhUSImageModule::getPhotometricInterpretation(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getPhotometricInterpretation(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getRows(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getRows(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_Rows, value, pos); + return m_Item->findAndGetUint16(DCM_Rows, value, pos); } - - -OFCondition IODEnhUSImageModule::getColumns(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getColumns(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_Columns, value, pos); + return m_Item->findAndGetUint16(DCM_Columns, value, pos); } - -OFCondition IODEnhUSImageModule::getBitsAllocated(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getBitsAllocated(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); + return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); } - -OFCondition IODEnhUSImageModule::getBitsStored(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getBitsStored(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); + return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); } - -OFCondition IODEnhUSImageModule::getHighBit(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getHighBit(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_HighBit, value, pos); + return m_Item->findAndGetUint16(DCM_HighBit, value, pos); } - -OFCondition IODEnhUSImageModule::getPixelRepresentation(Uint16& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getPixelRepresentation(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); + return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); } - -OFCondition IODEnhUSImageModule::getDimensionOrganizationType(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getDimensionOrganizationType(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getAcquisitionDateTime(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getAcquisitionDateTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getAcquisitionDuration(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getAcquisitionDuration(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_AcquisitionDuration, value, pos); + return m_Item->findAndGetFloat64(DCM_AcquisitionDuration, value, pos); } - -OFCondition IODEnhUSImageModule::getPixelSpacing(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getPixelSpacing(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_PixelSpacing, value, pos); + return m_Item->findAndGetFloat64(DCM_PixelSpacing, value, pos); } - -OFCondition IODEnhUSImageModule::getPositionMeasuringDevice(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getPositionMeasuringDevice(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PositionMeasuringDeviceUsed, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PositionMeasuringDeviceUsed, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getLossyImageCompression(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getLossyImageCompression(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getLossyImageCompressionRatio(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getLossyImageCompressionRatio(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_LossyImageCompressionRatio, value, pos); + return m_Item->findAndGetFloat64(DCM_LossyImageCompressionRatio, value, pos); } - OFCondition IODEnhUSImageModule::getLossyImageCompressionMethod(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getPresentationLUTShape(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getPresentationLUTShape(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getRescaleSlope(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getRescaleSlope(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_RescaleSlope, value, pos); + return m_Item->findAndGetFloat64(DCM_RescaleSlope, value, pos); } - -OFCondition IODEnhUSImageModule::getRescaleIntercept(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getRescaleIntercept(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_RescaleSlope, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_RescaleSlope, *m_Item, value, pos); } - GeneralAnatomyMacro& IODEnhUSImageModule::getAnatomy() { - return m_Anatomy; + return m_Anatomy; } - MandatoryViewAndSliceProgressionDirectionMacro& IODEnhUSImageModule::getMandatoryViewAndSliceProgressionDirection() { - return m_MandatoryViewAndSliceProgressionDirection; + return m_MandatoryViewAndSliceProgressionDirection; } - -OFCondition IODEnhUSImageModule::getBurnedInAnnotation(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getBurnedInAnnotation(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getRecognizableVisibleFeatures(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getRecognizableVisibleFeatures(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); } - CodeSequenceMacro& IODEnhUSImageModule::getTransducerScanPattern() { - return m_TransducerScanPattern; + return m_TransducerScanPattern; } - CodeSequenceMacro& IODEnhUSImageModule::getTransducerGeometry() { - return m_TransducerGeometry; + return m_TransducerGeometry; } - OFVector& IODEnhUSImageModule::getTransducerBeamSteering() { - return m_TransducerBeamSteering; + return m_TransducerBeamSteering; } - CodeSequenceMacro& IODEnhUSImageModule::getTransducerApplication() { - return m_TransducerApplication; + return m_TransducerApplication; } - -OFCondition IODEnhUSImageModule::getProcessingFunction(OFString& value, - const signed long pos) +OFCondition IODEnhUSImageModule::getProcessingFunction(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ProcessingFunction, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ProcessingFunction, *m_Item, value, pos); } - -OFCondition IODEnhUSImageModule::getMechanicalIndex(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getMechanicalIndex(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_MechanicalIndex, value, pos); + return m_Item->findAndGetFloat64(DCM_MechanicalIndex, value, pos); } - -OFCondition IODEnhUSImageModule::getBoneThermalIndex(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getBoneThermalIndex(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_BoneThermalIndex, value, pos); + return m_Item->findAndGetFloat64(DCM_BoneThermalIndex, value, pos); } - -OFCondition IODEnhUSImageModule::getCranialThermalIndex(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getCranialThermalIndex(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_CranialThermalIndex, value, pos); + return m_Item->findAndGetFloat64(DCM_CranialThermalIndex, value, pos); } - -OFCondition IODEnhUSImageModule::getSoftTissueThermalIndex(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getSoftTissueThermalIndex(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_SoftTissueThermalIndex, value, pos); + return m_Item->findAndGetFloat64(DCM_SoftTissueThermalIndex, value, pos); } - -OFCondition IODEnhUSImageModule::getDepthsOfFocus(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getDepthsOfFocus(Float64& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_DepthsOfFocus, value, pos); + return m_Item->findAndGetFloat64(DCM_DepthsOfFocus, value, pos); } - -OFCondition IODEnhUSImageModule::getDepthsOfScanField(Float64& value, - const unsigned long pos) +OFCondition IODEnhUSImageModule::getDepthsOfScanField(Sint32& value, const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_DepthsOfFocus, value, pos); + return m_Item->findAndGetSint32(DCM_DepthOfScanField, value, pos); } - // --- set attributes --- - OFCondition IODEnhUSImageModule::setImageType(const DcmIODTypes::IOD_ENHUSIMAGETYPE pixelDataChar, const OFString& imageFlavor, const OFString& derivedPixelContrast, const OFBool checkValue) { - OFString value; - switch (pixelDataChar) - { - case(DcmIODTypes::IMAGETYPE_ORIGINAL): value = "ORIGINAL\\PRIMARY\\"; break; - case(DcmIODTypes::IMAGETYPE_DERIVED) : value = "DERIVED\\PRIMARY\\"; break; - default: return IOD_EC_InvalidElementValue; - } - value += imageFlavor; - value += "\\"; - value += derivedPixelContrast; + OFString value; + switch (pixelDataChar) + { + case (DcmIODTypes::IMAGETYPE_ORIGINAL): + value = "ORIGINAL\\PRIMARY\\"; + break; + case (DcmIODTypes::IMAGETYPE_DERIVED): + value = "DERIVED\\PRIMARY\\"; + break; + default: + return IOD_EC_InvalidElementValue; + } + value += imageFlavor; + value += "\\"; + value += derivedPixelContrast; - OFCondition result; - if (checkValue) - { - result = DcmCodeString::checkStringValue(value, "2"); - } - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_ImageType, value); - } - return result; + OFCondition result; + if (checkValue) + { + result = DcmCodeString::checkStringValue(value, "2"); + } + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_ImageType, value); + } + return result; } - -OFCondition IODEnhUSImageModule::setRows(const Uint16 value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setRows(const Uint16 value, const OFBool checkValue) { - if (checkValue && (value == 0)) - return IOD_EC_InvalidElementValue; + if (checkValue && (value == 0)) + return IOD_EC_InvalidElementValue; - return m_Item->putAndInsertUint16(DCM_Rows, value); + return m_Item->putAndInsertUint16(DCM_Rows, value); } - -OFCondition IODEnhUSImageModule::setColumns(const Uint16 value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setColumns(const Uint16 value, const OFBool checkValue) { - if (checkValue && (value == 0)) - return IOD_EC_InvalidElementValue; + if (checkValue && (value == 0)) + return IOD_EC_InvalidElementValue; - return m_Item->putAndInsertUint16(DCM_Columns, value); + return m_Item->putAndInsertUint16(DCM_Columns, value); } - -OFCondition IODEnhUSImageModule::setBitsAllocated(const Uint16 value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setBitsAllocated(const Uint16 value, const OFBool checkValue) { - if (checkValue && (value != 8) && (value != 16)) - return IOD_EC_InvalidElementValue; + if (checkValue && (value != 8) && (value != 16)) + return IOD_EC_InvalidElementValue; - return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); + return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); } - -OFCondition IODEnhUSImageModule::setBitsStored(const Uint16 value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setBitsStored(const Uint16 value, const OFBool checkValue) { - if (checkValue && (value != 8) && (value != 16)) - return IOD_EC_InvalidElementValue; + if (checkValue && (value != 8) && (value != 16)) + return IOD_EC_InvalidElementValue; - return m_Item->putAndInsertUint16(DCM_BitsStored, value); + return m_Item->putAndInsertUint16(DCM_BitsStored, value); } - -OFCondition IODEnhUSImageModule::setHighBit(const Uint16 value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setHighBit(const Uint16 value, const OFBool checkValue) { - if (checkValue && (value != 7) && (value != 15)) - return IOD_EC_InvalidElementValue; + if (checkValue && (value != 7) && (value != 15)) + return IOD_EC_InvalidElementValue; - return m_Item->putAndInsertUint16(DCM_HighBit, value); + return m_Item->putAndInsertUint16(DCM_HighBit, value); } - -OFCondition IODEnhUSImageModule::setDimensionOrganizationType(const OFString& value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setDimensionOrganizationType(const OFString& value, const OFBool checkValue) { - OFCondition result; - if (checkValue) - { - if ( (value != "3D") && (value != "3D_TEMPORAL") ) - return IOD_EC_InvalidElementValue; - } - return m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); + OFCondition result; + if (checkValue) + { + if ((value != "3D") && (value != "3D_TEMPORAL")) + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); } - -OFCondition IODEnhUSImageModule::setAcquisitionDateTime(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setAcquisitionDateTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); - return result; + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); + return result; } - -OFCondition IODEnhUSImageModule::setAcquisitionDuration(const Float64 value, - const OFBool) +OFCondition IODEnhUSImageModule::setAcquisitionDuration(const Float64 value, const OFBool) { - return m_Item->putAndInsertFloat64(DCM_AcquisitionDuration, value); + return m_Item->putAndInsertFloat64(DCM_AcquisitionDuration, value); } - -OFCondition IODEnhUSImageModule::setPixelSpacing(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setPixelSpacing(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "2") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PixelSpacing, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "2") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PixelSpacing, value); + return result; } - -OFCondition IODEnhUSImageModule::setPositionMeasuringDevice(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setPositionMeasuringDevice(const OFString& value, const OFBool checkValue) { - OFCondition result; - if (checkValue) - { - result = DcmCodeString::checkStringValue(value, "1"); - if (result.good()) + OFCondition result; + if (checkValue) { - if ( (value != "RIGID") && (value != "FREEHAND") ) - result = IOD_EC_InvalidElementValue; + result = DcmCodeString::checkStringValue(value, "1"); + if (result.good()) + { + if ((value != "RIGID") && (value != "FREEHAND")) + result = IOD_EC_InvalidElementValue; + } } - } - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PositionMeasuringDeviceUsed, value); + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PositionMeasuringDeviceUsed, value); - return result; + return result; } - -OFCondition IODEnhUSImageModule::setLossyImageCompression(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setLossyImageCompression(const OFString& value, const OFBool checkValue) { - if (checkValue) - { - if ( (value != "00") && (value != "01") ) - return IOD_EC_InvalidElementValue; - } + if (checkValue) + { + if ((value != "00") && (value != "01")) + return IOD_EC_InvalidElementValue; + } - return m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); + return m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); } - - -OFCondition IODEnhUSImageModule::setLossyImageCompressionMethod(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setLossyImageCompressionMethod(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); + return result; } - -OFCondition IODEnhUSImageModule::setLossyImageCompressionRatio(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setLossyImageCompressionRatio(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); + return result; } - -OFCondition IODEnhUSImageModule::setRecognizableVisibleFeatures(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setRecognizableVisibleFeatures(const OFString& value, const OFBool checkValue) { - if (checkValue) - { - if ( (value != "NO" ) && (value != "YES") ) - return IOD_EC_InvalidElementValue; - } - return m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); + if (checkValue) + { + if ((value != "NO") && (value != "YES")) + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); } - -OFCondition IODEnhUSImageModule::setProcessingFunction(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setProcessingFunction(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ProcessingFunction, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ProcessingFunction, value); + return result; } - -OFCondition IODEnhUSImageModule::setMechanicalIndex(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setMechanicalIndex(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_MechanicalIndex, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_MechanicalIndex, value); + return result; } - -OFCondition IODEnhUSImageModule::setBoneThermalIndex(const OFString& value, - const OFBool checkValue) +OFCondition IODEnhUSImageModule::setBoneThermalIndex(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_BoneThermalIndex, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BoneThermalIndex, value); + return result; } - -OFCondition IODEnhUSImageModule::setCranialThermalIndex(const OFString& value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setCranialThermalIndex(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_CranialThermalIndex, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CranialThermalIndex, value); + return result; } - -OFCondition IODEnhUSImageModule::setSoftTissueThermalIndex(const OFString& value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setSoftTissueThermalIndex(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SoftTissueThermalIndex, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftTissueThermalIndex, value); + return result; } - -OFCondition IODEnhUSImageModule::setDepthsOfFocus(const Float64 value, - const long unsigned int pos, - const bool checkValue) +OFCondition +IODEnhUSImageModule::setDepthsOfFocus(const Float64 value, const long unsigned int pos, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_DepthsOfFocus, value, pos); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_DepthsOfFocus, value, pos); } - -OFCondition IODEnhUSImageModule::setDepthsOfFocus(const OFVector< Float64 >& values, - const bool checkValue) +OFCondition IODEnhUSImageModule::setDepthsOfFocus(const OFVector& values, const OFBool checkValue) { - (void)checkValue; - DcmElement* elem = DcmItem::newDicomElement(DCM_DepthsOfFocus); - if (!elem) - return EC_MemoryExhausted; + (void)checkValue; + DcmElement* elem = DcmItem::newDicomElement(DCM_DepthsOfFocus); + if (!elem) + return EC_MemoryExhausted; - OFCondition result; - OFVector::const_iterator it = values.begin(); - while ((it != values.end()) && result.good()) - { - result = elem->putFloat64(*it); - it++; - } - if (result.bad()) - { - delete elem; - } - else - { - result = m_Item->insert(elem); - } - return result; + OFCondition result; + OFVector::const_iterator it = values.begin(); + while ((it != values.end()) && result.good()) + { + result = elem->putFloat64(*it); + it++; + } + if (result.bad()) + { + delete elem; + } + else + { + result = m_Item->insert(elem); + } + return result; } - -OFCondition IODEnhUSImageModule::setDepthsOfScanField(const OFString& value, - const bool checkValue) +OFCondition IODEnhUSImageModule::setDepthsOfScanField(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DepthOfScanField, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DepthOfScanField, value); + return result; } diff --git a/dcmiod/libsrc/modenhusseries.cc b/dcmiod/libsrc/modenhusseries.cc index 932bf440..eba83877 100644 --- a/dcmiod/libsrc/modenhusseries.cc +++ b/dcmiod/libsrc/modenhusseries.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,102 +19,106 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modenhusseries.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODEnhancedUSSeriesModule::m_ModuleName = "EnhancedUSSeries"; - -IODEnhancedUSSeriesModule::IODEnhancedUSSeriesModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_ReferencedPerformedProcedureStep(), - m_PerformedProtocolCode() +IODEnhancedUSSeriesModule::IODEnhancedUSSeriesModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_ReferencedPerformedProcedureStep() + , m_PerformedProtocolCode() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODEnhancedUSSeriesModule::IODEnhancedUSSeriesModule() -: IODModule(), - m_ReferencedPerformedProcedureStep(), - m_PerformedProtocolCode() + : IODModule() + , m_ReferencedPerformedProcedureStep() + , m_PerformedProtocolCode() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODEnhancedUSSeriesModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODEnhancedUSSeriesModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_Modality, "1","1", getName(), DcmIODTypes::IE_SERIES, "US"), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_PerformedProtocolCodeSequence, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1", "1", getName(), DcmIODTypes::IE_SERIES, "US"), OFTrue); + m_Rules->addRule( + new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1", "1C", getName(), DcmIODTypes::IE_SERIES), + OFTrue); + m_Rules->addRule(new IODRule(DCM_PerformedProtocolCodeSequence, "1", "1C", getName(), DcmIODTypes::IE_SERIES), + OFTrue); } - -OFCondition IODEnhancedUSSeriesModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODEnhancedUSSeriesModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); - - IODComponent::read(source, OFFalse /* data already cleared */); - - DcmIODUtil::readSingleItem(source, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPerformedProcedureStep, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); - DcmIODUtil::readSingleItem(source, DCM_PerformedProtocolCodeSequence, m_PerformedProtocolCode, m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); - - return EC_Normal; + if (clearOldData) + clearData(); + + IODComponent::read(source, OFFalse /* data already cleared */); + + DcmIODUtil::readSingleItem( + source, + DCM_ReferencedPerformedProcedureStepSequence, + m_ReferencedPerformedProcedureStep, + m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + DcmIODUtil::readSingleItem(source, + DCM_PerformedProtocolCodeSequence, + m_PerformedProtocolCode, + m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); + + return EC_Normal; } - OFCondition IODEnhancedUSSeriesModule::write(DcmItem& destination) { - OFCondition result = EC_Normal; - - result = IODComponent::write(destination); - DcmIODUtil::writeSingleItem(result, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPerformedProcedureStep, destination, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); - DcmIODUtil::writeSingleItem(result, DCM_PerformedProtocolCodeSequence, m_PerformedProtocolCode, destination, m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); - - return result; + OFCondition result = EC_Normal; + + result = IODComponent::write(destination); + DcmIODUtil::writeSingleItem( + result, + DCM_ReferencedPerformedProcedureStepSequence, + m_ReferencedPerformedProcedureStep, + destination, + m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + DcmIODUtil::writeSingleItem(result, + DCM_PerformedProtocolCodeSequence, + m_PerformedProtocolCode, + destination, + m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); + + return result; } - IODEnhancedUSSeriesModule::~IODEnhancedUSSeriesModule() { } - -OFCondition IODEnhancedUSSeriesModule::getModality(OFString &value, - const signed long pos) const +OFCondition IODEnhancedUSSeriesModule::getModality(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); } - CodeSequenceMacro& IODEnhancedUSSeriesModule::getPerformedProtocolCode() { - return m_PerformedProtocolCode; + return m_PerformedProtocolCode; } - SOPInstanceReferenceMacro& IODEnhancedUSSeriesModule::getReferencedPPS() { - return m_ReferencedPerformedProcedureStep; + return m_ReferencedPerformedProcedureStep; } - -OFCondition IODEnhancedUSSeriesModule::getPerformedProtocolType(OFString &value, - const signed long pos) const +OFCondition IODEnhancedUSSeriesModule::getPerformedProtocolType(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PerformedProtocolType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PerformedProtocolType, *m_Item, value, pos); } diff --git a/dcmiod/libsrc/modequipment.cc b/dcmiod/libsrc/modequipment.cc index eadd5275..c45d2cff 100644 --- a/dcmiod/libsrc/modequipment.cc +++ b/dcmiod/libsrc/modequipment.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,188 +19,151 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modequipment.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcvrlo.h" -#include "dcmtk/dcmdata/dcvrst.h" #include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrst.h" #include "dcmtk/dcmiod/iodutil.h" -IODGeneralEquipmentModule::IODGeneralEquipmentModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_ModuleName("GeneralEquipmentModule") +IODGeneralEquipmentModule::IODGeneralEquipmentModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_ModuleName("GeneralEquipmentModule") { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODGeneralEquipmentModule::IODGeneralEquipmentModule() -: IODModule(), - m_ModuleName("GeneralEquipmentModule") + : IODModule() + , m_ModuleName("GeneralEquipmentModule") { - resetRules(); + resetRules(); } - void IODGeneralEquipmentModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_Manufacturer, "1", "2", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstitutionName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstitutionAddress, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_StationName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstitutionalDepartmentName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Manufacturer, "1", "2", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionAddress, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_StationName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionalDepartmentName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), + OFTrue); + m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n", "3", getName(), DcmIODTypes::IE_EQUIPMENT), OFTrue); } - IODGeneralEquipmentModule::~IODGeneralEquipmentModule() { } - OFString IODGeneralEquipmentModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - -OFCondition IODGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getManufacturer(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getManufacturer(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getInstitutionName(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getInstitutionName(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_InstitutionName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstitutionName, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getInstitutionAddress(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getInstitutionAddress(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_InstitutionAddress, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstitutionAddress, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getStationName(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getStationName(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getInstitutionalDepartmentName(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getInstitutionalDepartmentName(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getManufacturerModelName(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getManufacturerModelName(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::getSoftwareVersions(OFString& value, - const long signed int pos) const +OFCondition IODGeneralEquipmentModule::getSoftwareVersions(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); } - -OFCondition IODGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setManufacturer(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setManufacturer(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setInstitutionName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setInstitutionName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_InstitutionName, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstitutionName, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setInstitutionAddress(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setInstitutionAddress(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertOFStringArray(DCM_InstitutionAddress, value); + (void)checkValue; + return m_Item->putAndInsertOFStringArray(DCM_InstitutionAddress, value); } - -OFCondition IODGeneralEquipmentModule::setStationName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setStationName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StationName, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StationName, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setInstutionalDepartmentName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setInstutionalDepartmentName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_InstitutionalDepartmentName, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstitutionalDepartmentName, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setManufacturerModelName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setManufacturerModelName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); - return result; - + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); + return result; } - -OFCondition IODGeneralEquipmentModule::setSoftwareVersions(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralEquipmentModule::setSoftwareVersions(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); + return result; } diff --git a/dcmiod/libsrc/modfloatingpointimagepixel.cc b/dcmiod/libsrc/modfloatingpointimagepixel.cc index d5e1494e..979a4973 100644 --- a/dcmiod/libsrc/modfloatingpointimagepixel.cc +++ b/dcmiod/libsrc/modfloatingpointimagepixel.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,242 +19,217 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modfloatingpointimagepixel.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrfl.h" #include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcvrfl.h" #include "dcmtk/dcmiod/iodutil.h" -const OFString IODFloatingPointImagePixelModule::m_ModuleName = "FloatingPointImagePixelModule"; -const DcmTagKey IODFloatingPointImagePixelModule::pixel_data_tag = DCM_FloatPixelData; +const OFString IODFloatingPointImagePixelModule::m_ModuleName = "FloatingPointImagePixelModule"; +const DcmTagKey IODFloatingPointImagePixelModule::pixel_data_tag = DCM_FloatPixelData; const DcmTagKey IODDoubleFloatingPointImagePixelModule::pixel_data_tag = DCM_DoubleFloatPixelData; - IODFloatingPointImagePixelModule::IODFloatingPointImagePixelModule(OFshared_ptr item, OFshared_ptr rules) -: IODImagePixelBase(item, rules) + : IODImagePixelBase(item, rules) { - // reset element rules - resetRules(); - getData().putAndInsertUint16(DCM_BitsAllocated, 32); - getData().putAndInsertUint16(DCM_SamplesPerPixel, 1); - getData().putAndInsertUint16(DCM_PixelRepresentation, 1); - getData().putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); + // reset element rules + resetRules(); + getData().putAndInsertUint16(DCM_BitsAllocated, 32); + getData().putAndInsertUint16(DCM_SamplesPerPixel, 1); + getData().putAndInsertUint16(DCM_PixelRepresentation, 1); + getData().putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); } - OFString IODFloatingPointImagePixelModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODFloatingPointImagePixelModule::IODFloatingPointImagePixelModule() -: IODImagePixelBase() + : IODImagePixelBase() { - resetRules(); + resetRules(); } - IODFloatingPointImagePixelModule::~IODFloatingPointImagePixelModule() { - // nothing to do + // nothing to do } - void IODFloatingPointImagePixelModule::resetRules() { - // Parameters this module is responsible for. - m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_FloatPixelPaddingValue, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_FloatPixelPaddingRangeLimit, "1", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + // Parameters this module is responsible for. + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_FloatPixelPaddingValue, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_FloatPixelPaddingRangeLimit, "1", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), + OFTrue); } - -OFCondition IODFloatingPointImagePixelModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODFloatingPointImagePixelModule::read(DcmItem& source, const OFBool clearOldData) { - // Read common attributes - IODImagePixelBase::read(source, clearOldData); - // Read extra attributes of Floating Point Image Pixel Module - IODModule::read(source, clearOldData); - return EC_Normal; + // Read common attributes + IODImagePixelBase::read(source, clearOldData); + // Read extra attributes of Floating Point Image Pixel Module + IODModule::read(source, clearOldData); + return EC_Normal; } - OFCondition IODFloatingPointImagePixelModule::write(DcmItem& destination) { - // Write Photometric Interpretation fixed value for Floating Point Image Pixel Module - OFCondition result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); - // Write common attributes - if (result.good()) - { - result = IODImagePixelBase::write(destination); - } - // Write extra attributes of Floating Poing Image Pixel Module - if (result.good()) - { - result = IODModule::write(destination); - } - return result; + // Write Photometric Interpretation fixed value for Floating Point Image Pixel Module + OFCondition result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); + // Write common attributes + if (result.good()) + { + result = IODImagePixelBase::write(destination); + } + // Write extra attributes of Floating Poing Image Pixel Module + if (result.good()) + { + result = IODModule::write(destination); + } + return result; } - IODImagePixelBase::DataType IODFloatingPointImagePixelModule::getDataType() const { - return IODImagePixelBase::DATA_TYPE_FLOAT; + return IODImagePixelBase::DATA_TYPE_FLOAT; } - -OFCondition IODFloatingPointImagePixelModule::getFloatPixelPaddingValue(Float32& value, - const long pos) +OFCondition IODFloatingPointImagePixelModule::getFloatPixelPaddingValue(Float32& value, const unsigned long pos) { - return m_Item->findAndGetFloat32(DCM_FloatPixelPaddingValue, value, pos); + return m_Item->findAndGetFloat32(DCM_FloatPixelPaddingValue, value, pos); } - -OFCondition IODFloatingPointImagePixelModule::getFloatPixelPaddingRangeLimit(Float32& value, - const long pos) +OFCondition IODFloatingPointImagePixelModule::getFloatPixelPaddingRangeLimit(Float32& value, const unsigned long pos) { - return m_Item->findAndGetFloat32(DCM_FloatPixelPaddingRangeLimit, value, pos); + return m_Item->findAndGetFloat32(DCM_FloatPixelPaddingRangeLimit, value, pos); } - -OFCondition IODFloatingPointImagePixelModule::setFloatPixelPaddingValue(const Float32 value, - const OFBool checkValue) +OFCondition IODFloatingPointImagePixelModule::setFloatPixelPaddingValue(const Float32 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat32(DCM_FloatPixelPaddingValue, value); + (void)checkValue; + return m_Item->putAndInsertFloat32(DCM_FloatPixelPaddingValue, value); } - OFCondition IODFloatingPointImagePixelModule::setFloatPixelPaddingRangeLimit(const Float32 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat32(DCM_FloatPixelPaddingRangeLimit, value); + (void)checkValue; + return m_Item->putAndInsertFloat32(DCM_FloatPixelPaddingRangeLimit, value); } // ---------------- Double Floating Point Image Pixel Module ------------------ const OFString IODDoubleFloatingPointImagePixelModule::m_ModuleName = "DoubleFloatingPointImagePixelModule"; - IODDoubleFloatingPointImagePixelModule::IODDoubleFloatingPointImagePixelModule(OFshared_ptr item, OFshared_ptr rules) -: IODImagePixelBase(item, rules) + : IODImagePixelBase(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); - getData().putAndInsertUint16(DCM_BitsAllocated, 64); - getData().putAndInsertUint16(DCM_SamplesPerPixel, 1); - getData().putAndInsertUint16(DCM_PixelRepresentation, 1); - getData().putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); + getData().putAndInsertUint16(DCM_BitsAllocated, 64); + getData().putAndInsertUint16(DCM_SamplesPerPixel, 1); + getData().putAndInsertUint16(DCM_PixelRepresentation, 1); + getData().putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); } - OFString IODDoubleFloatingPointImagePixelModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODDoubleFloatingPointImagePixelModule::IODDoubleFloatingPointImagePixelModule() -: IODImagePixelBase() + : IODImagePixelBase() { - resetRules(); + resetRules(); } - IODDoubleFloatingPointImagePixelModule::~IODDoubleFloatingPointImagePixelModule() { - // nothing to do + // nothing to do } - void IODDoubleFloatingPointImagePixelModule::resetRules() { - // Parameters are tag, VM, type. Overwrite old rules if any. - // Take over responsibility for Photometric Interpretation since we want to write - // "MONOCHROME2" as a fixed value. - m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "MONOCHROME2"), OFTrue); - m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DoubleFloatPixelPaddingValue, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DoubleFloatPixelPaddingRangeLimit, "1", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + // Parameters are tag, VM, type. Overwrite old rules if any. + // Take over responsibility for Photometric Interpretation since we want to write + // "MONOCHROME2" as a fixed value. + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule( + new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE, "MONOCHROME2"), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DoubleFloatPixelPaddingValue, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_DoubleFloatPixelPaddingRangeLimit, "1", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), + OFTrue); } - -OFCondition IODDoubleFloatingPointImagePixelModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODDoubleFloatingPointImagePixelModule::read(DcmItem& source, const OFBool clearOldData) { - // Read common attributes - IODImagePixelBase::read(source, clearOldData); - // Read extra attributes of Floating Point Image Pixel Module - IODModule::read(source, clearOldData); - return EC_Normal; + // Read common attributes + IODImagePixelBase::read(source, clearOldData); + // Read extra attributes of Floating Point Image Pixel Module + IODModule::read(source, clearOldData); + return EC_Normal; } - OFCondition IODDoubleFloatingPointImagePixelModule::write(DcmItem& destination) { - // Write Photometric Interpretation fixed value for Floating Point Image Pixel Module - OFCondition result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); - // Write common attributes - if (result.good()) - { - result = IODImagePixelBase::write(destination); - } - // Write extra attributes of Floating Poing Image Pixel Module - if (result.good()) - { - result = IODModule::write(destination); - } - return result; + // Write Photometric Interpretation fixed value for Floating Point Image Pixel Module + OFCondition result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); + // Write common attributes + if (result.good()) + { + result = IODImagePixelBase::write(destination); + } + // Write extra attributes of Floating Poing Image Pixel Module + if (result.good()) + { + result = IODModule::write(destination); + } + return result; } - IODImagePixelBase::DataType IODDoubleFloatingPointImagePixelModule::getDataType() const { - return IODImagePixelBase::DATA_TYPE_DOUBLE; + return IODImagePixelBase::DATA_TYPE_DOUBLE; } - OFCondition IODDoubleFloatingPointImagePixelModule::getDoubleFloatPixelPaddingValue(Float64& value, - const long pos) + const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_FloatPixelPaddingValue, value, pos); + return m_Item->findAndGetFloat64(DCM_FloatPixelPaddingValue, value, pos); } - OFCondition IODDoubleFloatingPointImagePixelModule::getDoubleFloatPixelPaddingRangeLimit(Float64& value, - const long pos) + const unsigned long pos) { - return m_Item->findAndGetFloat64(DCM_DoubleFloatPixelPaddingRangeLimit, value, pos); + return m_Item->findAndGetFloat64(DCM_DoubleFloatPixelPaddingRangeLimit, value, pos); } - OFCondition IODDoubleFloatingPointImagePixelModule::setDoubleFloatPixelPaddingValue(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_DoubleFloatPixelPaddingValue, value); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_DoubleFloatPixelPaddingValue, value); } - OFCondition IODDoubleFloatingPointImagePixelModule::setDoubleFloatPixelPaddingRangeLimit(const Float64 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertFloat64(DCM_DoubleFloatPixelPaddingRangeLimit, value); + (void)checkValue; + return m_Item->putAndInsertFloat64(DCM_DoubleFloatPixelPaddingRangeLimit, value); } diff --git a/dcmiod/libsrc/modfor.cc b/dcmiod/libsrc/modfor.cc index 3e331666..f664fb0e 100644 --- a/dcmiod/libsrc/modfor.cc +++ b/dcmiod/libsrc/modfor.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,101 +19,85 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modfor.h" -#include "dcmtk/dcmdata/dcvrui.h" -#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODFoRModule::m_ModuleName = "FrameOfReferenceModule"; - -IODFoRModule::IODFoRModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODFoRModule::IODFoRModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODFoRModule::IODFoRModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODFoRModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_FrameOfReferenceUID, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_PositionReferenceIndicator, "1","2", getName(), DcmIODTypes::IE_FOR), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_FrameOfReferenceUID, "1", "1", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_PositionReferenceIndicator, "1", "2", getName(), DcmIODTypes::IE_FOR), OFTrue); } - OFString IODFoRModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODFoRModule::~IODFoRModule() { - // Nothing to do + // Nothing to do } - -OFCondition IODFoRModule::getFrameOfReferenceUID(OFString& value, - const signed long pos) const +OFCondition IODFoRModule::getFrameOfReferenceUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_FrameOfReferenceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_FrameOfReferenceUID, *m_Item, value, pos); } - -OFCondition IODFoRModule::getPositionReferenceIndicator(OFString& value, - const signed long pos) const +OFCondition IODFoRModule::getPositionReferenceIndicator(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PositionReferenceIndicator, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PositionReferenceIndicator, *m_Item, value, pos); } - -OFCondition IODFoRModule::setFrameOfReferenceUID(const OFString &value, - const OFBool checkValue) +OFCondition IODFoRModule::setFrameOfReferenceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, value); + return result; } - -OFCondition IODFoRModule::setPositionReferenceIndicator(const OFString &value, - const OFBool checkValue) +OFCondition IODFoRModule::setPositionReferenceIndicator(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, value); + return result; } - void IODFoRModule::ensureFrameOfReferenceUID(const OFBool correctInvalid) { - OFString uidstr; + OFString uidstr; - // Create new Frame of Reference instance UID if required - if (getFrameOfReferenceUID(uidstr).bad() || uidstr.empty() ) - { - setFrameOfReferenceUID(DcmIODUtil::createUID(1 /* Series Level */)); - } - else if (!uidstr.empty() && correctInvalid) - { - if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + // Create new Frame of Reference instance UID if required + if (getFrameOfReferenceUID(uidstr).bad() || uidstr.empty()) + { + setFrameOfReferenceUID(DcmIODUtil::createUID(1 /* Series Level */)); + } + else if (!uidstr.empty() && correctInvalid) { - setFrameOfReferenceUID(DcmIODUtil::createUID(1 /* Series Level */)); + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setFrameOfReferenceUID(DcmIODUtil::createUID(1 /* Series Level */)); + } } - } } - diff --git a/dcmiod/libsrc/modgeneralimage.cc b/dcmiod/libsrc/modgeneralimage.cc index 3b71561d..247f3607 100644 --- a/dcmiod/libsrc/modgeneralimage.cc +++ b/dcmiod/libsrc/modgeneralimage.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2020, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,359 +19,298 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modgeneralimage.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrui.h" -#include "dcmtk/dcmdata/dcvrtm.h" -#include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrda.h" #include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcvris.h" -#include "dcmtk/dcmdata/dcvrda.h" #include "dcmtk/dcmdata/dcvrlt.h" - +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODGeneralImageModule::m_ModuleName = "GeneralImageModule"; - -IODGeneralImageModule::IODGeneralImageModule( OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODGeneralImageModule::IODGeneralImageModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODGeneralImageModule::IODGeneralImageModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - IODGeneralImageModule::~IODGeneralImageModule() { } - void IODGeneralImageModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "2", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientOrientation, "2", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ImageType, "2-n", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionNumber, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionDate, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionTime, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ImageComments, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_IrradiationEventUID, "1-n", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "2", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientOrientation, "2", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "2C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ImageType, "2-n", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionNumber, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDate, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionTime, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ImageComments, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n", "3", getName(), DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_IrradiationEventUID, "1-n", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); } - OFString IODGeneralImageModule::getName() const { - return "GeneralImageModule"; + return "GeneralImageModule"; } - - -OFCondition IODGeneralImageModule::getInstanceNumber(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getInstanceNumber(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_InstanceNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstanceNumber, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getPatientOrientation(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getPatientOrientation(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PatientOrientation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientOrientation, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getContentDate(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getContentDate(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getContentTime(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getContentTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getImageType(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getImageType(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getAcquisitionNumber(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getAcquisitionNumber(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionNumber, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getAcquisitionDate(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getAcquisitionDate(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDate, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDate, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getAcquisitionTime(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getAcquisitionTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTime, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getAcquisitionDateTime(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getAcquisitionDateTime(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getImageComments(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getImageComments(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ImageComments, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ImageComments, *m_Item, value, pos); } -OFCondition IODGeneralImageModule::getBurnedInAnnotation(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getBurnedInAnnotation(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getRecognizableVisualFeatures(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getRecognizableVisualFeatures(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getLossyImageCompression(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getLossyImageCompression(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getLossyImageCompressionRatio(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getLossyImageCompressionRatio(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionRatio, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionRatio, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getLossyImageCompressionMethod(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getLossyImageCompressionMethod(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getPresentationLUTShape(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getPresentationLUTShape(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::getIrradiationEventUID(OFString &value, - const signed long pos) +OFCondition IODGeneralImageModule::getIrradiationEventUID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_IrradiationEventUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_IrradiationEventUID, *m_Item, value, pos); } - -OFCondition IODGeneralImageModule::setInstanceNumber(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setInstanceNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); + return result; } - -OFCondition IODGeneralImageModule::setPatientOrientation(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setPatientOrientation(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientOrientation, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientOrientation, value); + return result; } - -OFCondition IODGeneralImageModule::setContentDate(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setContentDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); + return result; } - -OFCondition IODGeneralImageModule::setContentTime(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setContentTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); + return result; } - -OFCondition IODGeneralImageModule::setImageType(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setImageType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ImageType, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ImageType, value); + return result; } - -OFCondition IODGeneralImageModule::setAcquisitionNumber(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setAcquisitionNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionNumber, value); + return result; } - -OFCondition IODGeneralImageModule::setAcquisitionDate(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setAcquisitionDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDate, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDate, value); + return result; } - -OFCondition IODGeneralImageModule::setAcquisitionTime(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setAcquisitionTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionTime, value); - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionTime, value); + return result; } - -OFCondition IODGeneralImageModule::setAcquisitionDateTime(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setAcquisitionDateTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); - return result; + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); + return result; } - -OFCondition IODGeneralImageModule::setImageComments(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setImageComments(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertOFStringArray(DCM_ImageComments, value); + (void)checkValue; + return m_Item->putAndInsertOFStringArray(DCM_ImageComments, value); } - -OFCondition IODGeneralImageModule::setBurnedInAnnotation(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setBurnedInAnnotation(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_BurnedInAnnotation, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BurnedInAnnotation, value); + return result; } - - -OFCondition IODGeneralImageModule::setRecognizableVisualFeatures(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setRecognizableVisualFeatures(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); + return result; } - - -OFCondition IODGeneralImageModule::setLossyImageCompression(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setLossyImageCompression(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); + return result; } - - -OFCondition IODGeneralImageModule::setLossyImageCompressionRatio(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setLossyImageCompressionRatio(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); + return result; } - -OFCondition IODGeneralImageModule::setLossyImageCompressionMethod(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setLossyImageCompressionMethod(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); + return result; } - -OFCondition IODGeneralImageModule::setPresentationLUTShape(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setLossyImageCompressionFlag(const OFString& ratios, + const OFString& methods, + const OFBool checkValues) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PresentationLUTShape, value); - return result; + OFCondition result = setLossyImageCompression("01", checkValues); + if (result.good() || !checkValues) + result = setLossyImageCompressionMethod(methods, checkValues); + if (result.good() || !checkValues) + result = setLossyImageCompressionRatio(ratios, checkValues); + + if (checkValues) + return result; + else + return EC_Normal; } +OFCondition IODGeneralImageModule::setPresentationLUTShape(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PresentationLUTShape, value); + return result; +} -OFCondition IODGeneralImageModule::setIrradiationEventUID(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralImageModule::setIrradiationEventUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_IrradiationEventUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_IrradiationEventUID, value); + return result; } diff --git a/dcmiod/libsrc/modgeneralseries.cc b/dcmiod/libsrc/modgeneralseries.cc index 8849fd19..aad100ed 100644 --- a/dcmiod/libsrc/modgeneralseries.cc +++ b/dcmiod/libsrc/modgeneralseries.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,333 +19,289 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modgeneralseries.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcvrcs.h" -#include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrda.h" #include "dcmtk/dcmdata/dcvris.h" -#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODGeneralSeriesModule::m_ModuleName = "GeneralSeriesModule"; - -IODGeneralSeriesModule::IODGeneralSeriesModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_ReferencedPPS() +IODGeneralSeriesModule::IODGeneralSeriesModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_ReferencedPPS() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODGeneralSeriesModule::IODGeneralSeriesModule() -: IODModule(), - m_ReferencedPPS() + : IODModule() + , m_ReferencedPPS() { - resetRules(); + resetRules(); } - OFString IODGeneralSeriesModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODGeneralSeriesModule::inventMissing() { - // Series Instance UID - ensureInstanceUID(); + // Series Instance UID + ensureInstanceUID(); - // Default handler - IODComponent::inventMissing(); + // Default handler + IODComponent::inventMissing(); } - void IODGeneralSeriesModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_Modality, "1","1", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1","1", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1","2", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_Laterality, "1","2C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesDate, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesTime, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_PerformingPhysicianName, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ProtocolName, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesDescription, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_OperatorsName, "1-n","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_BodyPartExamined, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientPosition, "1","2C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1","3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1", "1", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1", "1", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1", "2", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_Laterality, "1", "2C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesDate, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesTime, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PerformingPhysicianName, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ProtocolName, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesDescription, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_OperatorsName, "1-n", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_BodyPartExamined, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientPosition, "1", "2C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule( + new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1", "3", getName(), DcmIODTypes::IE_SERIES), OFTrue); } - -OFCondition IODGeneralSeriesModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODGeneralSeriesModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - IODComponent::read(source, OFFalse /* data already cleared */); - DcmIODUtil::readSingleItem(source, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPPS, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + IODComponent::read(source, OFFalse /* data already cleared */); + DcmIODUtil::readSingleItem( + source, + DCM_ReferencedPerformedProcedureStepSequence, + m_ReferencedPPS, + m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); - return EC_Normal; + return EC_Normal; } - OFCondition IODGeneralSeriesModule::write(DcmItem& destination) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - result = IODComponent::write(destination); - DcmIODUtil::writeSingleItem(result, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPPS, destination, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + result = IODComponent::write(destination); + DcmIODUtil::writeSingleItem( + result, + DCM_ReferencedPerformedProcedureStepSequence, + m_ReferencedPPS, + destination, + m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); - return result; + return result; } - void IODGeneralSeriesModule::ensureInstanceUID(const OFBool correctInvalid) { - OFString uidstr; + OFString uidstr; - /* create new sop instance UID if required */ - if (getSeriesInstanceUID(uidstr).bad() || uidstr.empty() ) - { - setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); - } - else if (!uidstr.empty() && correctInvalid) - { - if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + /* create new sop instance UID if required */ + if (getSeriesInstanceUID(uidstr).bad() || uidstr.empty()) { - setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); } - } + setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); + } + else if (!uidstr.empty() && correctInvalid) + { + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); + } + } } - IODGeneralSeriesModule::~IODGeneralSeriesModule() { } - -OFCondition IODGeneralSeriesModule::getModality(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getModality(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getSeriesInstanceUID(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getSeriesInstanceUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getSeriesNumber(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getSeriesNumber(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getLaterality(OFString& value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getLaterality(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Laterality, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Laterality, *m_Item, value, pos); } - - -OFCondition IODGeneralSeriesModule::getSeriesDate(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getSeriesDate(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesDate, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesDate, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getSeriesTime(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getSeriesTime(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesTime, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getPerformingPhysicianName(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getPerformingPhysicianName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PerformingPhysicianName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PerformingPhysicianName, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getProtocolName(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getProtocolName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ProtocolName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ProtocolName, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getSeriesDescription(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getSeriesDescription(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesDescription, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesDescription, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getOperatorsName(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getOperatorsName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_OperatorsName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_OperatorsName, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getBodyPartExamined(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getBodyPartExamined(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_BodyPartExamined, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_BodyPartExamined, *m_Item, value, pos); } - -OFCondition IODGeneralSeriesModule::getPatientPosition(OFString &value, - const signed long pos) const +OFCondition IODGeneralSeriesModule::getPatientPosition(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientPosition, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientPosition, *m_Item, value, pos); } - SOPInstanceReferenceMacro& IODGeneralSeriesModule::getReferencedPPS() { - return m_ReferencedPPS; + return m_ReferencedPPS; } - -OFCondition IODGeneralSeriesModule::setModality(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setModality(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_Modality, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Modality, value); + return result; } - -OFCondition IODGeneralSeriesModule::setSeriesInstanceUID(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setSeriesInstanceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); + return result; } - -OFCondition IODGeneralSeriesModule::setSeriesNumber(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setSeriesNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); + return result; } - -OFCondition IODGeneralSeriesModule::setLaterality(const DcmIODTypes::IOD_LATERALITY laterality, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setLaterality(const DcmIODTypes::IOD_LATERALITY laterality, const OFBool checkValue) { - (void)checkValue; - OFCondition result; - switch(laterality) - { - case DcmIODTypes::LATERALITY_L: result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "L"); break; - case DcmIODTypes::LATERALITY_R: result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "R"); break; - case DcmIODTypes::LATERALITY_UNDEFINED: - default: result = IOD_EC_InvalidLaterality; - } - return result; + (void)checkValue; + OFCondition result; + switch (laterality) + { + case DcmIODTypes::LATERALITY_L: + result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "L"); + break; + case DcmIODTypes::LATERALITY_R: + result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "R"); + break; + case DcmIODTypes::LATERALITY_UNDEFINED: + default: + result = IOD_EC_InvalidLaterality; + } + return result; } - -OFCondition IODGeneralSeriesModule::setSeriesDate(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setSeriesDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesDate, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesDate, value); + return result; } - -OFCondition IODGeneralSeriesModule::setSeriesTime(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setSeriesTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesTime, value); - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesTime, value); + return result; } - -OFCondition IODGeneralSeriesModule::setPerformingPhysicianName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setPerformingPhysicianName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PerformingPhysicianName, value); - return result; + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PerformingPhysicianName, value); + return result; } - -OFCondition IODGeneralSeriesModule::setProtocolName(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setProtocolName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ProtocolName, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ProtocolName, value); + return result; } - -OFCondition IODGeneralSeriesModule::setSeriesDescription(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setSeriesDescription(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesDescription, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesDescription, value); + return result; } - OFCondition IODGeneralSeriesModule::setOperatorsName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_OperatorsName, value); - return result; + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_OperatorsName, value); + return result; } - -OFCondition IODGeneralSeriesModule::setBodyPartExamined(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setBodyPartExamined(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_BodyPartExamined, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BodyPartExamined, value); + return result; } - -OFCondition IODGeneralSeriesModule::setPatientPosition(const OFString& value, - const OFBool checkValue) +OFCondition IODGeneralSeriesModule::setPatientPosition(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientPosition, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientPosition, value); + return result; } diff --git a/dcmiod/libsrc/modgeneralstudy.cc b/dcmiod/libsrc/modgeneralstudy.cc index e5102b4d..ef9d62fa 100644 --- a/dcmiod/libsrc/modgeneralstudy.cc +++ b/dcmiod/libsrc/modgeneralstudy.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,279 +19,254 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modgeneralstudy.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcuid.h" -#include "dcmtk/dcmdata/dcvrpn.h" -#include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrda.h" -#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrpn.h" #include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODGeneralStudyModule::m_ModuleName = "GeneralStudyModule"; - -IODGeneralStudyModule::IODGeneralStudyModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules), - m_IssuerOfAccessionNumberSequence(), - m_ProcedureCodeSequence(), - m_ReasonForPerformedProcedureCodeSequence() +IODGeneralStudyModule::IODGeneralStudyModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) + , m_IssuerOfAccessionNumberSequence() + , m_ProcedureCodeSequence() + , m_ReasonForPerformedProcedureCodeSequence() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODGeneralStudyModule::IODGeneralStudyModule() -: IODModule(), - m_IssuerOfAccessionNumberSequence(), - m_ProcedureCodeSequence(), - m_ReasonForPerformedProcedureCodeSequence() + : IODModule() + , m_IssuerOfAccessionNumberSequence() + , m_ProcedureCodeSequence() + , m_ReasonForPerformedProcedureCodeSequence() { - resetRules(); + resetRules(); } - void IODGeneralStudyModule::inventMissing() { - // Study Instance UID - ensureInstanceUID(); + // Study Instance UID + ensureInstanceUID(); - IODComponent::inventMissing(); + IODComponent::inventMissing(); } - void IODGeneralStudyModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1","1", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_StudyDate, "1","2", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_StudyTime, "1","2", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferringPhysicianName, "1","2", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_StudyID, "1","2", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_AccessionNumber, "1","2", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_StudyDescription, "1","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_IssuerOfAccessionNumberSequence, "1","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_ProcedureCodeSequence, "1-n","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReasonForPerformedProcedureCodeSequence, "1-n","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1", "1", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyDate, "1", "2", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyTime, "1", "2", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferringPhysicianName, "1", "2", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyID, "1", "2", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_AccessionNumber, "1", "2", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyDescription, "1", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_IssuerOfAccessionNumberSequence, "1", "3", getName(), DcmIODTypes::IE_STUDY), + OFTrue); + m_Rules->addRule(new IODRule(DCM_ProcedureCodeSequence, "1-n", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule( + new IODRule(DCM_ReasonForPerformedProcedureCodeSequence, "1-n", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); } - OFString IODGeneralStudyModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODGeneralStudyModule::clearData() { - m_IssuerOfAccessionNumberSequence.clearData(); - DcmIODUtil::freeContainer(m_ProcedureCodeSequence); - DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); + m_IssuerOfAccessionNumberSequence.clearData(); + DcmIODUtil::freeContainer(m_ProcedureCodeSequence); + DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); } - -OFCondition IODGeneralStudyModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODGeneralStudyModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - { - clearData(); - } + if (clearOldData) + { + clearData(); + } - IODComponent::read(source, OFFalse /* data already cleared above */); + IODComponent::read(source, OFFalse /* data already cleared above */); - DcmIODUtil::readSingleItem(source, DCM_IssuerOfAccessionNumberSequence, m_IssuerOfAccessionNumberSequence, m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); - DcmIODUtil::readSubSequence(source, DCM_ProcedureCodeSequence, m_ProcedureCodeSequence, m_Rules->getByTag(DCM_ProcedureCodeSequence)); - DcmIODUtil::readSubSequence(source, DCM_ReasonForPerformedProcedureCodeSequence, m_ReasonForPerformedProcedureCodeSequence, m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); + DcmIODUtil::readSingleItem(source, + DCM_IssuerOfAccessionNumberSequence, + m_IssuerOfAccessionNumberSequence, + m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); + DcmIODUtil::readSubSequence( + source, DCM_ProcedureCodeSequence, m_ProcedureCodeSequence, m_Rules->getByTag(DCM_ProcedureCodeSequence)); + DcmIODUtil::readSubSequence(source, + DCM_ReasonForPerformedProcedureCodeSequence, + m_ReasonForPerformedProcedureCodeSequence, + m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); - return EC_Normal; + return EC_Normal; } - OFCondition IODGeneralStudyModule::write(DcmItem& destination) { - OFCondition result; - DcmIODUtil::writeSingleItem(result, DCM_IssuerOfAccessionNumberSequence, m_IssuerOfAccessionNumberSequence, *m_Item, m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); - DcmIODUtil::writeSubSequence(result, DCM_ProcedureCodeSequence, m_ProcedureCodeSequence, *m_Item, m_Rules->getByTag(DCM_ProcedureCodeSequence)); - DcmIODUtil::writeSubSequence(result, DCM_ReasonForPerformedProcedureCodeSequence, m_ReasonForPerformedProcedureCodeSequence, *m_Item, m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); + OFCondition result; + DcmIODUtil::writeSingleItem(result, + DCM_IssuerOfAccessionNumberSequence, + m_IssuerOfAccessionNumberSequence, + *m_Item, + m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); + DcmIODUtil::writeSubSequence(result, + DCM_ProcedureCodeSequence, + m_ProcedureCodeSequence, + *m_Item, + m_Rules->getByTag(DCM_ProcedureCodeSequence)); + DcmIODUtil::writeSubSequence(result, + DCM_ReasonForPerformedProcedureCodeSequence, + m_ReasonForPerformedProcedureCodeSequence, + *m_Item, + m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); - if (result.good()) result = IODComponent::write(destination); + if (result.good()) + result = IODComponent::write(destination); - return result; + return result; } - - - IODGeneralStudyModule::~IODGeneralStudyModule() { - DcmIODUtil::freeContainer(m_ProcedureCodeSequence); - DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); + DcmIODUtil::freeContainer(m_ProcedureCodeSequence); + DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); } - void IODGeneralStudyModule::ensureInstanceUID(const OFBool correctInvalid) { - OFString uidstr; - - /* create new sop instance UID if required */ - if (getStudyInstanceUID(uidstr).bad() || uidstr.empty() ) - { - setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); - } - else if (!uidstr.empty() && correctInvalid) - { - if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + OFString uidstr; + + /* create new sop instance UID if required */ + if (getStudyInstanceUID(uidstr).bad() || uidstr.empty()) + { + setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); + } + else if (!uidstr.empty() && correctInvalid) { - setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); + } } - } } - // --- get attributes (C++ string) --- -OFCondition IODGeneralStudyModule::getStudyInstanceUID(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getStudyInstanceUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getReferringPhysicianName(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getReferringPhysicianName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_ReferringPhysicianName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ReferringPhysicianName, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getStudyDescription(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getStudyDescription(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyDescription, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StudyDescription, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getStudyDate(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getStudyDate(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyDate, *m_Item, value, pos); - + return DcmIODUtil::getStringValueFromItem(DCM_StudyDate, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getStudyTime(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getStudyTime(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StudyTime, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getStudyID(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getStudyID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_StudyID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_StudyID, *m_Item, value, pos); } - -OFCondition IODGeneralStudyModule::getAccessionNumber(OFString &value, - const signed long pos) const +OFCondition IODGeneralStudyModule::getAccessionNumber(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_AccessionNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AccessionNumber, *m_Item, value, pos); } - -HL7HierarchicDesignatorMacro& IODGeneralStudyModule::getIssuerOfAccesionNumber() +HL7HierarchicDesignatorMacro& IODGeneralStudyModule::getIssuerOfAccessionNumber() { - return m_IssuerOfAccessionNumberSequence; + return m_IssuerOfAccessionNumberSequence; } - -OFVector< CodeSequenceMacro* >& IODGeneralStudyModule::getProcedureCodeSequence() +OFVector& IODGeneralStudyModule::getProcedureCodeSequence() { - return m_ProcedureCodeSequence; + return m_ProcedureCodeSequence; } - -OFVector< CodeSequenceMacro* >& IODGeneralStudyModule::getReasonForPerformedProcedureCodeSequence() +OFVector& IODGeneralStudyModule::getReasonForPerformedProcedureCodeSequence() { - return m_ReasonForPerformedProcedureCodeSequence; + return m_ReasonForPerformedProcedureCodeSequence; } - // --- set attributes --- -OFCondition IODGeneralStudyModule::setReferringPhysicianName(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setReferringPhysicianName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ReferringPhysicianName,value); - return result; + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferringPhysicianName, value); + return result; } - -OFCondition IODGeneralStudyModule::setStudyDescription(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setStudyDescription(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyDescription,value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyDescription, value); + return result; } - -OFCondition IODGeneralStudyModule::setStudyInstanceUID(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setStudyInstanceUID(const OFString& value, const OFBool checkValue) { OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID,value); + result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID, value); return result; } - -OFCondition IODGeneralStudyModule::setStudyDate(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setStudyDate(const OFString& value, const OFBool checkValue) { OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyDate, value); + result = m_Item->putAndInsertOFStringArray(DCM_StudyDate, value); return result; } - -OFCondition IODGeneralStudyModule::setStudyTime(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setStudyTime(const OFString& value, const OFBool checkValue) { OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyTime,value); + result = m_Item->putAndInsertOFStringArray(DCM_StudyTime, value); return result; } - -OFCondition IODGeneralStudyModule::setStudyID(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setStudyID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_StudyID, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyID, value); + return result; } - -OFCondition IODGeneralStudyModule::setAccessionNumber(const OFString &value, - const OFBool checkValue) +OFCondition IODGeneralStudyModule::setAccessionNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AccessionNumber, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AccessionNumber, value); + return result; } - diff --git a/dcmiod/libsrc/modhelp.cc b/dcmiod/libsrc/modhelp.cc index 44ee4231..aa923315 100644 --- a/dcmiod/libsrc/modhelp.cc +++ b/dcmiod/libsrc/modhelp.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,327 +19,280 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modhelp.h" -#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" - +#include "dcmtk/dcmdata/dcitem.h" // List of tags within the Patient Module -const DcmTagKey DcmModuleHelpers::patientModuleTags[] = -{ - DCM_PatientName, - DCM_PatientID, - // Macro IssuerOfPatientIDMacro - DCM_IssuerOfPatientID, - DCM_IssuerOfPatientIDQualifiersSequence, - // EndMacro IssuerOfPatientIDMacro - DCM_PatientBirthDate, - DCM_PatientSex, - DCM_QualityControlSubject, - DCM_ReferencedPatientSequence, - DCM_PatientBirthTime, - DCM_RETIRED_OtherPatientIDs, - DCM_OtherPatientIDsSequence, - DCM_OtherPatientNames, - DCM_EthnicGroup, - DCM_PatientComments, - DCM_PatientSpeciesDescription, - DCM_PatientSpeciesCodeSequence, - DCM_PatientBreedDescription, - DCM_PatientBreedCodeSequence, - DCM_BreedRegistrationSequence, - DCM_ResponsiblePerson, - DCM_ResponsiblePersonRole, - DCM_ResponsibleOrganization, - DCM_PatientIdentityRemoved, - DCM_DeidentificationMethod, - DCM_DeidentificationMethodCodeSequence -}; +const DcmTagKey DcmModuleHelpers::patientModuleTags[] = { DCM_PatientName, + DCM_PatientID, + // Macro IssuerOfPatientIDMacro + DCM_IssuerOfPatientID, + DCM_IssuerOfPatientIDQualifiersSequence, + // EndMacro IssuerOfPatientIDMacro + DCM_PatientBirthDate, + DCM_PatientSex, + DCM_QualityControlSubject, + DCM_ReferencedPatientSequence, + DCM_PatientBirthTime, + DCM_RETIRED_OtherPatientIDs, + DCM_OtherPatientIDsSequence, + DCM_OtherPatientNames, + DCM_EthnicGroup, + DCM_PatientComments, + DCM_PatientSpeciesDescription, + DCM_PatientSpeciesCodeSequence, + DCM_PatientBreedDescription, + DCM_PatientBreedCodeSequence, + DCM_BreedRegistrationSequence, + DCM_ResponsiblePerson, + DCM_ResponsiblePersonRole, + DCM_ResponsibleOrganization, + DCM_PatientIdentityRemoved, + DCM_DeidentificationMethod, + DCM_DeidentificationMethodCodeSequence }; // List of tags within the Clinical Trial Subject Module -const DcmTagKey DcmModuleHelpers::clinicalTrialSubjectModuleTags[] = -{ - DCM_ClinicalTrialSponsorName, - DCM_ClinicalTrialProtocolID, - DCM_ClinicalTrialProtocolName, - DCM_ClinicalTrialSiteID, - DCM_ClinicalTrialSiteName, - DCM_ClinicalTrialSubjectID, - DCM_ClinicalTrialSubjectReadingID, - DCM_ClinicalTrialProtocolEthicsCommitteeName, - DCM_ClinicalTrialProtocolEthicsCommitteeApprovalNumber -}; +const DcmTagKey DcmModuleHelpers::clinicalTrialSubjectModuleTags[] + = { DCM_ClinicalTrialSponsorName, + DCM_ClinicalTrialProtocolID, + DCM_ClinicalTrialProtocolName, + DCM_ClinicalTrialSiteID, + DCM_ClinicalTrialSiteName, + DCM_ClinicalTrialSubjectID, + DCM_ClinicalTrialSubjectReadingID, + DCM_ClinicalTrialProtocolEthicsCommitteeName, + DCM_ClinicalTrialProtocolEthicsCommitteeApprovalNumber }; // List of tags within the General Study Module -const DcmTagKey DcmModuleHelpers::generalStudyModuleTags[] = -{ - DCM_StudyInstanceUID, - DCM_StudyDate, - DCM_StudyTime, - DCM_ReferringPhysicianName, - DCM_ReferringPhysicianIdentificationSequence, - DCM_StudyID, - DCM_AccessionNumber, - DCM_IssuerOfAccessionNumberSequence, - DCM_StudyDescription, - DCM_PhysiciansOfRecord, - DCM_PhysiciansOfRecordIdentificationSequence, - DCM_NameOfPhysiciansReadingStudy, - DCM_PhysiciansReadingStudyIdentificationSequence, - DCM_RequestingServiceCodeSequence, - DCM_ReferencedStudySequence, - DCM_ProcedureCodeSequence, - DCM_ReasonForPerformedProcedureCodeSequence -}; +const DcmTagKey DcmModuleHelpers::generalStudyModuleTags[] = { DCM_StudyInstanceUID, + DCM_StudyDate, + DCM_StudyTime, + DCM_ReferringPhysicianName, + DCM_ReferringPhysicianIdentificationSequence, + DCM_StudyID, + DCM_AccessionNumber, + DCM_IssuerOfAccessionNumberSequence, + DCM_StudyDescription, + DCM_PhysiciansOfRecord, + DCM_PhysiciansOfRecordIdentificationSequence, + DCM_NameOfPhysiciansReadingStudy, + DCM_PhysiciansReadingStudyIdentificationSequence, + DCM_RequestingServiceCodeSequence, + DCM_ReferencedStudySequence, + DCM_ProcedureCodeSequence, + DCM_ReasonForPerformedProcedureCodeSequence }; // List of tags within the Patient Study Module -const DcmTagKey DcmModuleHelpers::patientStudyModuleTags[] = -{ - DCM_AdmittingDiagnosesDescription, - DCM_AdmittingDiagnosesCodeSequence, - DCM_PatientAge, - DCM_PatientSize, - DCM_PatientWeight, - DCM_PatientSizeCodeSequence, - DCM_Occupation, - DCM_AdditionalPatientHistory, - DCM_AdmissionID, - DCM_IssuerOfAdmissionIDSequence, - DCM_ServiceEpisodeID, - DCM_IssuerOfServiceEpisodeIDSequence, - DCM_ServiceEpisodeDescription, - DCM_PatientSexNeutered -}; +const DcmTagKey DcmModuleHelpers::patientStudyModuleTags[] = { DCM_AdmittingDiagnosesDescription, + DCM_AdmittingDiagnosesCodeSequence, + DCM_PatientAge, + DCM_PatientSize, + DCM_PatientWeight, + DCM_PatientSizeCodeSequence, + DCM_Occupation, + DCM_AdditionalPatientHistory, + DCM_AdmissionID, + DCM_IssuerOfAdmissionIDSequence, + DCM_ServiceEpisodeID, + DCM_IssuerOfServiceEpisodeIDSequence, + DCM_ServiceEpisodeDescription, + DCM_PatientSexNeutered }; // List of tags within the Clinical Trial Study Module -const DcmTagKey DcmModuleHelpers::clinicalTrialStudyModuleTags[] = -{ - DCM_ClinicalTrialTimePointID, - DCM_ClinicalTrialTimePointDescription, - DCM_ConsentForClinicalTrialUseSequence -}; +const DcmTagKey DcmModuleHelpers::clinicalTrialStudyModuleTags[] + = { DCM_ClinicalTrialTimePointID, DCM_ClinicalTrialTimePointDescription, DCM_ConsentForClinicalTrialUseSequence }; // List of tags within the General Series Module -const DcmTagKey DcmModuleHelpers::generalSeriesModuleTags[] = -{ - DCM_Modality, - DCM_SeriesInstanceUID, - DCM_SeriesNumber, - DCM_Laterality, - DCM_SeriesDate, - DCM_SeriesTime, - DCM_PerformingPhysicianName, - DCM_PerformingPhysicianIdentificationSequence, - DCM_ProtocolName, - DCM_SeriesDescription, - DCM_SeriesDescriptionCodeSequence, - DCM_OperatorsName, - DCM_OperatorIdentificationSequence, - DCM_ReferencedPerformedProcedureStepSequence, - DCM_RelatedSeriesSequence, - DCM_BodyPartExamined, - DCM_PatientPosition, - DCM_SmallestPixelValueInSeries, - DCM_LargestPixelValueInSeries, - DCM_RequestAttributesSequence, - // Macro PerformedProcedureStepSummaryMacro - DCM_PerformedProcedureStepID, - DCM_PerformedProcedureStepStartDate, - DCM_PerformedProcedureStepStartTime, - DCM_PerformedProcedureStepEndDate, - DCM_PerformedProcedureStepEndTime, - DCM_PerformedProcedureStepDescription, - DCM_PerformedProtocolCodeSequence, - DCM_CommentsOnThePerformedProcedureStep, - // EndMacro PerformedProcedureStepSummaryMacro - DCM_AnatomicalOrientationType -}; +const DcmTagKey DcmModuleHelpers::generalSeriesModuleTags[] = { DCM_Modality, + DCM_SeriesInstanceUID, + DCM_SeriesNumber, + DCM_Laterality, + DCM_SeriesDate, + DCM_SeriesTime, + DCM_PerformingPhysicianName, + DCM_PerformingPhysicianIdentificationSequence, + DCM_ProtocolName, + DCM_SeriesDescription, + DCM_SeriesDescriptionCodeSequence, + DCM_OperatorsName, + DCM_OperatorIdentificationSequence, + DCM_ReferencedPerformedProcedureStepSequence, + DCM_RelatedSeriesSequence, + DCM_BodyPartExamined, + DCM_PatientPosition, + DCM_SmallestPixelValueInSeries, + DCM_LargestPixelValueInSeries, + DCM_RequestAttributesSequence, + // Macro PerformedProcedureStepSummaryMacro + DCM_PerformedProcedureStepID, + DCM_PerformedProcedureStepStartDate, + DCM_PerformedProcedureStepStartTime, + DCM_PerformedProcedureStepEndDate, + DCM_PerformedProcedureStepEndTime, + DCM_PerformedProcedureStepDescription, + DCM_PerformedProtocolCodeSequence, + DCM_CommentsOnThePerformedProcedureStep, + // EndMacro PerformedProcedureStepSummaryMacro + DCM_AnatomicalOrientationType }; // List of tags within the Clinical Trial Series Module -const DcmTagKey DcmModuleHelpers::clinicalTrialSeriesModuleTags[] = -{ - DCM_ClinicalTrialCoordinatingCenterName, - DCM_ClinicalTrialSeriesID, - DCM_ClinicalTrialSeriesDescription -}; +const DcmTagKey DcmModuleHelpers::clinicalTrialSeriesModuleTags[] + = { DCM_ClinicalTrialCoordinatingCenterName, DCM_ClinicalTrialSeriesID, DCM_ClinicalTrialSeriesDescription }; // List of tags within the General Equipment Module -const DcmTagKey DcmModuleHelpers::generalEquipmentModuleTags[] = -{ - DCM_Manufacturer, - DCM_InstitutionName, - DCM_InstitutionAddress, - DCM_StationName, - DCM_InstitutionalDepartmentName, - DCM_ManufacturerModelName, - DCM_DeviceSerialNumber, - DCM_SoftwareVersions, - DCM_GantryID, - DCM_SpatialResolution, - DCM_DateOfLastCalibration, - DCM_TimeOfLastCalibration, - DCM_PixelPaddingValue -}; +const DcmTagKey DcmModuleHelpers::generalEquipmentModuleTags[] = { DCM_Manufacturer, + DCM_InstitutionName, + DCM_InstitutionAddress, + DCM_StationName, + DCM_InstitutionalDepartmentName, + DCM_ManufacturerModelName, + DCM_DeviceSerialNumber, + DCM_SoftwareVersions, + DCM_GantryID, + DCM_SpatialResolution, + DCM_DateOfLastCalibration, + DCM_TimeOfLastCalibration, + DCM_PixelPaddingValue }; // List of tags within the Frame of Reference Module -const DcmTagKey DcmModuleHelpers::frameOfReferenceModuleTags[] = -{ - DCM_FrameOfReferenceUID, - DCM_PositionReferenceIndicator -}; +const DcmTagKey DcmModuleHelpers::frameOfReferenceModuleTags[] + = { DCM_FrameOfReferenceUID, DCM_PositionReferenceIndicator }; // List of tags within the SOP Common Module, excluding Digital Signatures Macro -const DcmTagKey DcmModuleHelpers::sopCommonModuleTags[] = -{ - DCM_SOPClassUID, - DCM_SOPInstanceUID, - DCM_SpecificCharacterSet, - DCM_InstanceCreationDate, - DCM_InstanceCreationTime, - DCM_InstanceCoercionDateTime, - DCM_InstanceCreatorUID, - DCM_RelatedGeneralSOPClassUID, - DCM_OriginalSpecializedSOPClassUID, - DCM_CodingSchemeIdentificationSequence, - DCM_TimezoneOffsetFromUTC, - DCM_ContributingEquipmentSequence, - DCM_InstanceNumber, - DCM_SOPInstanceStatus, - DCM_SOPAuthorizationDateTime, - DCM_SOPAuthorizationComment, - DCM_AuthorizationEquipmentCertificationNumber, - // Macro DigitalSignaturesMacro - //DCM_MACParametersSequence, - //DCM_DigitalSignaturesSequence, - // EndMacro DigitalSignaturesMacro - DCM_EncryptedAttributesSequence, - DCM_OriginalAttributesSequence, - DCM_HL7StructuredDocumentReferenceSequence, - DCM_LongitudinalTemporalInformationModified, - DCM_QueryRetrieveView, - DCM_ConversionSourceAttributesSequence -}; +const DcmTagKey DcmModuleHelpers::sopCommonModuleTags[] = { DCM_SOPClassUID, + DCM_SOPInstanceUID, + DCM_SpecificCharacterSet, + DCM_InstanceCreationDate, + DCM_InstanceCreationTime, + DCM_InstanceCoercionDateTime, + DCM_InstanceCreatorUID, + DCM_RelatedGeneralSOPClassUID, + DCM_OriginalSpecializedSOPClassUID, + DCM_CodingSchemeIdentificationSequence, + DCM_TimezoneOffsetFromUTC, + DCM_ContributingEquipmentSequence, + DCM_InstanceNumber, + DCM_SOPInstanceStatus, + DCM_SOPAuthorizationDateTime, + DCM_SOPAuthorizationComment, + DCM_AuthorizationEquipmentCertificationNumber, + // Macro DigitalSignaturesMacro + // DCM_MACParametersSequence, + // DCM_DigitalSignaturesSequence, + // EndMacro DigitalSignaturesMacro + DCM_EncryptedAttributesSequence, + DCM_OriginalAttributesSequence, + DCM_HL7StructuredDocumentReferenceSequence, + DCM_LongitudinalTemporalInformationModified, + DCM_QueryRetrieveView, + DCM_ConversionSourceAttributesSequence }; // List of tags within the General Image Module -const DcmTagKey DcmModuleHelpers::generalImageModuleTags[] = -{ - DCM_InstanceNumber, - DCM_PatientOrientation, - DCM_ContentDate, - DCM_ContentTime, - DCM_ImageType, - DCM_AcquisitionNumber, - DCM_AcquisitionDate, - DCM_AcquisitionTime, - DCM_AcquisitionDateTime, - DCM_ReferencedImageSequence, - DCM_DerivationDescription, - DCM_DerivationCodeSequence, - DCM_SourceImageSequence, - DCM_ReferencedInstanceSequence, - DCM_ImagesInAcquisition, - DCM_ImageComments, - DCM_QualityControlImage, - DCM_BurnedInAnnotation, - DCM_RecognizableVisualFeatures, - DCM_LossyImageCompression, - DCM_LossyImageCompressionRatio, - DCM_LossyImageCompressionMethod, - DCM_IconImageSequence, - DCM_PresentationLUTShape, - DCM_IrradiationEventUID, - DCM_RealWorldValueMappingSequence -}; - +const DcmTagKey DcmModuleHelpers::generalImageModuleTags[] = { DCM_InstanceNumber, + DCM_PatientOrientation, + DCM_ContentDate, + DCM_ContentTime, + DCM_ImageType, + DCM_AcquisitionNumber, + DCM_AcquisitionDate, + DCM_AcquisitionTime, + DCM_AcquisitionDateTime, + DCM_ReferencedImageSequence, + DCM_DerivationDescription, + DCM_DerivationCodeSequence, + DCM_SourceImageSequence, + DCM_ReferencedInstanceSequence, + DCM_ImagesInAcquisition, + DCM_ImageComments, + DCM_QualityControlImage, + DCM_BurnedInAnnotation, + DCM_RecognizableVisualFeatures, + DCM_LossyImageCompression, + DCM_LossyImageCompressionRatio, + DCM_LossyImageCompressionMethod, + DCM_IconImageSequence, + DCM_PresentationLUTShape, + DCM_IrradiationEventUID, + DCM_RealWorldValueMappingSequence }; void DcmModuleHelpers::copyElement(const DcmTagKey& tag, DcmItem& src, DcmItem& dest) { - DcmElement *delem; - OFCondition cond; - // get (deep) copy of element - cond = src.findAndGetElement(tag, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); - if (cond.good()) - { - // and insert into destination item - cond = dest.insert(delem, OFTrue); - if (cond.bad()) + DcmElement* delem; + OFCondition cond; + // get (deep) copy of element + cond = src.findAndGetElement(tag, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); + if (cond.good()) { - // we do not expect any errors here, so report it - DCMDATA_ERROR("Could not insert element with tag " << tag << " into item: " << cond.text()); + // and insert into destination item + cond = dest.insert(delem, OFTrue); + if (cond.bad()) + { + // we do not expect any errors here, so report it + DCMDATA_ERROR("Could not insert element with tag " << tag << " into item: " << cond.text()); + } } - } } -template -inline void DcmModuleHelpers::copyModule( const DcmTagKey (&tags)[N], DcmItem& src, DcmItem& dest ) +template +inline void DcmModuleHelpers::copyModule(const DcmTagKey (&tags)[N], DcmItem& src, DcmItem& dest) { - for (const DcmTagKey* it = tags, * const end = tags + N; it != end; ++it) - DcmModuleHelpers::copyElement(*it, src, dest); + for (const DcmTagKey *it = tags, *const end = tags + N; it != end; ++it) + DcmModuleHelpers::copyElement(*it, src, dest); } - void DcmModuleHelpers::copyPatientModule(DcmItem& src, DcmItem& dest) { - copyModule(patientModuleTags, src, dest); + copyModule(patientModuleTags, src, dest); } - void DcmModuleHelpers::copyClinicalTrialSubjectModule(DcmItem& src, DcmItem& dest) { - copyModule(clinicalTrialSubjectModuleTags, src, dest); + copyModule(clinicalTrialSubjectModuleTags, src, dest); } - void DcmModuleHelpers::copyGeneralStudyModule(DcmItem& src, DcmItem& dest) { - copyModule(generalStudyModuleTags, src, dest); + copyModule(generalStudyModuleTags, src, dest); } - void DcmModuleHelpers::copyPatientStudyModule(DcmItem& src, DcmItem& dest) { - copyModule(patientStudyModuleTags, src, dest); + copyModule(patientStudyModuleTags, src, dest); } - void DcmModuleHelpers::copyClinicalTrialStudyModule(DcmItem& src, DcmItem& dest) { - copyModule(clinicalTrialStudyModuleTags, src, dest); + copyModule(clinicalTrialStudyModuleTags, src, dest); } - void DcmModuleHelpers::copyGeneralSeriesModule(DcmItem& src, DcmItem& dest) { - copyModule(generalSeriesModuleTags, src, dest); + copyModule(generalSeriesModuleTags, src, dest); } - void DcmModuleHelpers::copyClinicalTrialSeriesModule(DcmItem& src, DcmItem& dest) { - copyModule(clinicalTrialSeriesModuleTags, src, dest); + copyModule(clinicalTrialSeriesModuleTags, src, dest); } - void DcmModuleHelpers::copyGeneralEquipmentModule(DcmItem& src, DcmItem& dest) { - copyModule(generalEquipmentModuleTags, src, dest); + copyModule(generalEquipmentModuleTags, src, dest); } - void DcmModuleHelpers::copyFrameOfReferenceModule(DcmItem& src, DcmItem& dest) { - copyModule(frameOfReferenceModuleTags, src, dest); + copyModule(frameOfReferenceModuleTags, src, dest); } - void DcmModuleHelpers::copySOPCommonModule(DcmItem& src, DcmItem& dest) { - copyModule(sopCommonModuleTags, src, dest); + copyModule(sopCommonModuleTags, src, dest); } - void DcmModuleHelpers::copyGeneralImageModule(DcmItem& src, DcmItem& dest) { - copyModule(generalImageModuleTags, src, dest); + copyModule(generalImageModuleTags, src, dest); } diff --git a/dcmiod/libsrc/modimagepixel.cc b/dcmiod/libsrc/modimagepixel.cc index 8d0b7b20..05609846 100644 --- a/dcmiod/libsrc/modimagepixel.cc +++ b/dcmiod/libsrc/modimagepixel.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2017, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,243 +19,229 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modimagepixel.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmiod/iodutil.h" -template +template const OFString IODImagePixelModule::m_ModuleName = "ImagePixelModule"; -template +template const DcmTagKey IODImagePixelModule::pixel_data_tag = DCM_PixelData; -template -IODImagePixelModule::IODImagePixelModule(OFshared_ptr item, - OFshared_ptr rules) -: IODImagePixelBase(item, rules) +template +IODImagePixelModule::IODImagePixelModule(OFshared_ptr item, OFshared_ptr rules) + : IODImagePixelBase(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } -template +template OFString IODImagePixelModule::getName() const { - return m_ModuleName; + return m_ModuleName; } -template +template IODImagePixelModule::IODImagePixelModule() -: IODImagePixelBase() + : IODImagePixelBase() { - resetRules(); + resetRules(); } -template +template IODImagePixelModule::~IODImagePixelModule() { } -template +template void IODImagePixelModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_BitsStored, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_HighBit, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PlanarConfiguration, "1", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ICCProfile, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsStored, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_HighBit, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PlanarConfiguration, "1", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ICCProfile, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue); } -template -OFCondition IODImagePixelModule::read(DcmItem& source, - const OFBool clearOldData) +template +OFCondition IODImagePixelModule::read(DcmItem& source, const OFBool clearOldData) { - // Read common attributes - IODImagePixelBase::read(source, clearOldData); - // Read extra attributes of Image Pixel Module - IODModule::read(source, clearOldData); - return EC_Normal; + // Read common attributes + IODImagePixelBase::read(source, clearOldData); + // Read extra attributes of Image Pixel Module + IODModule::read(source, clearOldData); + return EC_Normal; } -template +template OFCondition IODImagePixelModule::write(DcmItem& destination) { - // Write common attributes - OFCondition result = IODImagePixelBase::write(destination); - // Write extra attributes of Image Pixel Module - if (result.good()) - { - IODModule::write(destination); - } - return result; + // Write common attributes + OFCondition result = IODImagePixelBase::write(destination); + // Write extra attributes of Image Pixel Module + if (result.good()) + { + IODModule::write(destination); + } + return result; } -template +template IODImagePixelBase::DataType IODImagePixelModule::getDataType() const { - return IODImagePixelBase::DATA_TYPE_INTEGER; + return IODImagePixelBase::DATA_TYPE_INTEGER; } -template -OFCondition IODImagePixelModule::getBitsStored(Uint16& value, - const signed long pos) +template +OFCondition IODImagePixelModule::getBitsStored(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); + return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); } -template -OFCondition IODImagePixelModule::getHighBit(Uint16& value, - const signed long pos) +template +OFCondition IODImagePixelModule::getHighBit(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_HighBit, value, pos); + return m_Item->findAndGetUint16(DCM_HighBit, value, pos); } -template -OFCondition IODImagePixelModule::getPixelRepresentation(Uint16& value, - const signed long pos) +template +OFCondition IODImagePixelModule::getPixelRepresentation(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); + return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); } -template -OFCondition IODImagePixelModule::getPlanarConfiguration(Uint16& value, - const signed long pos) +template +OFCondition IODImagePixelModule::getPlanarConfiguration(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_PlanarConfiguration, value, pos); + return m_Item->findAndGetUint16(DCM_PlanarConfiguration, value, pos); } -template +template OFCondition IODImagePixelModule::getICCProfile(OFVector& values) { - DcmElement* elem = NULL; - OFCondition result = m_Item->findAndGetElement(DCM_ICCProfile, elem); - if (result.good()) - { - DcmOtherByteOtherWord* ob = OFstatic_cast(DcmOtherByteOtherWord*, elem); - if (ob) - return DcmIODUtil::copyFromUint8Array > (ob, values); + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_ICCProfile, elem); + if (result.good()) + { + DcmOtherByteOtherWord* ob = OFstatic_cast(DcmOtherByteOtherWord*, elem); + if (ob) + return DcmIODUtil::copyFromUint8Array >(ob, values); + else + return EC_InternalError; + } else - return EC_InternalError; - } - else - return EC_TagNotFound; + return EC_TagNotFound; } -template -OFCondition IODImagePixelModule::setSamplesPerPixel(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setSamplesPerPixel(const Uint16 value, const OFBool checkValue) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - // only values 1, 3 and 4 (retired) are permitted - if (checkValue) - { - if ( (value == 0) || (value == 2) || (value > 4) ) + // only values 1, 3 and 4 (retired) are permitted + if (checkValue) { - DCMIOD_ERROR("Value " << value << " not permitted for attribute Samples Per Pixel"); - result = EC_InvalidValue; + if ((value == 0) || (value == 2) || (value > 4)) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Samples Per Pixel"); + result = EC_InvalidValue; + } + else if (value == 4) + { + DCMIOD_WARN("Value " << value << " is retired for attribute Samples Per Pixel"); + } } - else if (value == 4) - { - DCMIOD_WARN("Value " << value << " is retired for attribute Samples Per Pixel"); - } - } - if (result.good() ) - result = m_Item->putAndInsertUint16(DCM_SamplesPerPixel, value); + if (result.good()) + result = m_Item->putAndInsertUint16(DCM_SamplesPerPixel, value); - return result; + return result; } -template -OFCondition IODImagePixelModule::setPhotometricInterpretation(const OFString& value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setPhotometricInterpretation(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, value); + return result; } -template -OFCondition IODImagePixelModule::setBitsAllocated(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setBitsAllocated(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); } -template -OFCondition IODImagePixelModule::setBitsStored(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setBitsStored(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_BitsStored, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_BitsStored, value); } -template -OFCondition IODImagePixelModule::setHighBit(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setHighBit(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_HighBit, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_HighBit, value); } -template -OFCondition IODImagePixelModule::setPixelRepresentation(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setPixelRepresentation(const Uint16 value, const OFBool checkValue) { - OFCondition result = EC_Normal; - if (checkValue) - { - if ( (value != 0) && (value != 1) ) + OFCondition result = EC_Normal; + if (checkValue) + { + if ((value != 0) && (value != 1)) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Pixel Representation"); + result = EC_InvalidValue; + } + } + if (result.good()) { - DCMIOD_ERROR("Value " << value << " not permitted for attribute Pixel Representation"); - result = EC_InvalidValue; + result = m_Item->putAndInsertUint16(DCM_PixelRepresentation, value); } - } - if ( result.good() ) - { - result = m_Item->putAndInsertUint16(DCM_PixelRepresentation, value); - } - return result; + return result; } -template -OFCondition IODImagePixelModule::setPlanarConfiguration(const Uint16 value, - const OFBool checkValue) +template +OFCondition IODImagePixelModule::setPlanarConfiguration(const Uint16 value, const OFBool checkValue) { - OFCondition result = EC_Normal; - if (checkValue) - { - if ( (value != 0) && (value != 1) ) + OFCondition result = EC_Normal; + if (checkValue) + { + if ((value != 0) && (value != 1)) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Planar Configuration"); + result = EC_InvalidValue; + } + } + if (result.good()) { - DCMIOD_ERROR("Value " << value << " not permitted for attribute Planar Configuration"); - result = EC_InvalidValue; + result = m_Item->putAndInsertUint16(DCM_PlanarConfiguration, value); } - } - if ( result.good() ) - { - result = m_Item->putAndInsertUint16(DCM_PlanarConfiguration, value); - } - return result; + return result; } -template -OFCondition IODImagePixelModule::setICCProfile(const Uint8* values, - const size_t length) +template +OFCondition IODImagePixelModule::setICCProfile(const Uint8* values, const size_t length) { - return m_Item->putAndInsertUint8Array(DCM_ICCProfile, values, OFstatic_cast(unsigned long, length)); + return m_Item->putAndInsertUint8Array(DCM_ICCProfile, values, OFstatic_cast(unsigned long, length)); } template class IODImagePixelModule; diff --git a/dcmiod/libsrc/modimagepixelbase.cc b/dcmiod/libsrc/modimagepixelbase.cc index f35725e5..cd83c7be 100644 --- a/dcmiod/libsrc/modimagepixelbase.cc +++ b/dcmiod/libsrc/modimagepixelbase.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -15,124 +15,103 @@ * * Author: Michael Onken * - * Purpose: Base class for Image Pixel Module and related (e.g. Ploating Point) + * Purpose: Base class for Image Pixel Module and related (e.g. Floating Point) * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modimagepixelbase.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" -#include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODImagePixelBase::m_ModuleName = "ImagePixelBase"; - -IODImagePixelBase::IODImagePixelBase(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODImagePixelBase::IODImagePixelBase(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODImagePixelBase::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODImagePixelBase::IODImagePixelBase() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - IODImagePixelBase::~IODImagePixelBase() { } - void IODImagePixelBase::resetRules() { - // all rules in sub classes + // all rules in sub classes } - -OFCondition IODImagePixelBase::getSamplesPerPixel(Uint16 &value, - const signed long pos) +OFCondition IODImagePixelBase::getSamplesPerPixel(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); + return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); } - -OFCondition IODImagePixelBase::getPhotometricInterpretation(OFString&value, - const signed long pos) +OFCondition IODImagePixelBase::getPhotometricInterpretation(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); } - -OFCondition IODImagePixelBase::getRows(Uint16& value, - const signed long pos) +OFCondition IODImagePixelBase::getRows(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_Rows, value, pos); + return m_Item->findAndGetUint16(DCM_Rows, value, pos); } - -OFCondition IODImagePixelBase::getColumns(Uint16& value, - const signed long pos) +OFCondition IODImagePixelBase::getColumns(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_Columns, value, pos); + return m_Item->findAndGetUint16(DCM_Columns, value, pos); } - -OFCondition IODImagePixelBase::getBitsAllocated(Uint16& value, - const signed long pos) +OFCondition IODImagePixelBase::getBitsAllocated(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); + return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); } - -OFCondition IODImagePixelBase::getPixelAspectRatio(Uint16& value, - const signed long pos) +OFCondition IODImagePixelBase::getPixelAspectRatio(Uint16& value, const unsigned long pos) { - return m_Item->findAndGetUint16(DCM_PixelAspectRatio, value, pos); + return m_Item->findAndGetUint16(DCM_PixelAspectRatio, value, pos); } - -OFCondition IODImagePixelBase::setRows(const Uint16 value, - const OFBool checkValue) +OFCondition IODImagePixelBase::setRows(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_Rows, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_Rows, value); } - -OFCondition IODImagePixelBase::setColumns(const Uint16 value, - const OFBool checkValue) +OFCondition IODImagePixelBase::setColumns(const Uint16 value, const OFBool checkValue) { - (void)checkValue; - return m_Item->putAndInsertUint16(DCM_Columns, value); + (void)checkValue; + return m_Item->putAndInsertUint16(DCM_Columns, value); } - OFCondition IODImagePixelBase::setPixelAspectRatio(const OFString& verticalPixelSize, - const OFString& horizontalPixelSize, - const OFBool checkValue) + const OFString& horizontalPixelSize, + const OFBool checkValue) { - OFString concat = verticalPixelSize; - concat += "\\"; concat += horizontalPixelSize; - OFCondition cond; - if (checkValue) - { - cond = DcmIntegerString::checkStringValue(concat, "2"); - // check for unsignedness, too? - } - if (cond.good()) m_Item->putAndInsertOFStringArray(DCM_PixelAspectRatio, concat); - return cond; + OFString concat = verticalPixelSize; + concat += "\\"; + concat += horizontalPixelSize; + OFCondition cond; + if (checkValue) + { + cond = DcmIntegerString::checkStringValue(concat, "2"); + // check for unsignedness, too? + } + if (cond.good()) + m_Item->putAndInsertOFStringArray(DCM_PixelAspectRatio, concat); + return cond; } diff --git a/dcmiod/libsrc/modmultiframedimension.cc b/dcmiod/libsrc/modmultiframedimension.cc index 906cafcd..de0c2318 100644 --- a/dcmiod/libsrc/modmultiframedimension.cc +++ b/dcmiod/libsrc/modmultiframedimension.cc @@ -19,39 +19,35 @@ * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/modmultiframedimension.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcpath.h" // for private tag reservation checking #include "dcmtk/dcmdata/dcvrat.h" +#include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrui.h" -#include "dcmtk/dcmdata/dcvrcs.h" -#include "dcmtk/dcmdata/dcpath.h" // for private tag reservation checking #include "dcmtk/dcmiod/iodutil.h" // for static helpers const OFString IODMultiframeDimensionModule::m_ModuleName = "MultiframeDimensionModule"; - -IODMultiframeDimensionModule::IODMultiframeDimensionModule(OFshared_ptr data, - OFshared_ptr rules) : - IODModule(data, rules), - m_DimensionIndexSequence(), - m_DimensionOrganizationSequence() +IODMultiframeDimensionModule::IODMultiframeDimensionModule(OFshared_ptr data, OFshared_ptr rules) + : IODModule(data, rules) + , m_DimensionIndexSequence() + , m_DimensionOrganizationSequence() { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODMultiframeDimensionModule::IODMultiframeDimensionModule() -: IODModule(), - m_DimensionIndexSequence(), - m_DimensionOrganizationSequence() + : IODModule() + , m_DimensionIndexSequence() + , m_DimensionOrganizationSequence() { - resetRules(); + resetRules(); } - OFCondition IODMultiframeDimensionModule::addDimensionIndex(const DcmTagKey& dimensionIndexPointer, const OFString& dimensionOrganizationUID, const DcmTagKey& functionalGroupPointer, @@ -59,591 +55,599 @@ OFCondition IODMultiframeDimensionModule::addDimensionIndex(const DcmTagKey& dim const OFString& dimensionIndexPrivateCreator, const OFString& functionalGroupPrivateCreator) { - if ( (dimensionIndexPointer.isPrivate() && dimensionIndexPrivateCreator.empty()) || - (functionalGroupPointer.isPrivate() && functionalGroupPrivateCreator.empty()) ) - { - DCMIOD_ERROR("Cannot add private Dimension Index without private creator"); - return IOD_EC_MissingAttribute; - } - - if (dimensionOrganizationUID.empty()) - { - DCMIOD_ERROR("Cannot add Dimension Index without Dimension Organization UID"); - return IOD_EC_MissingAttribute; - } - - // Add Dimension Organization by its UID if such organization does not exist yet - OFVector::iterator it = m_DimensionOrganizationSequence.begin(); - while (it != m_DimensionOrganizationSequence.end()) - { - OFString val; - (*it)->getDimensionOrganizationUID(val); - if (val == dimensionOrganizationUID) + if ((dimensionIndexPointer.isPrivate() && dimensionIndexPrivateCreator.empty()) + || (functionalGroupPointer.isPrivate() && functionalGroupPrivateCreator.empty())) { - break; + DCMIOD_ERROR("Cannot add private Dimension Index without private creator"); + return IOD_EC_MissingAttribute; } - it++; - } - OFCondition result; - if (it == m_DimensionOrganizationSequence.end()) - { - DimensionOrganizationItem* item = new DimensionOrganizationItem; - if (item == NULL) + + if (dimensionOrganizationUID.empty()) { - return EC_MemoryExhausted; + DCMIOD_ERROR("Cannot add Dimension Index without Dimension Organization UID"); + return IOD_EC_MissingAttribute; } - result = item->setDimensionOrganizationUID(dimensionOrganizationUID); - if (result.bad()) - return result; - m_DimensionOrganizationSequence.push_back(item); - } - // Create dimension and add it to this object - DimensionIndexItem* dim = new DimensionIndexItem(); - if (!dim) - return EC_MemoryExhausted; + // Add Dimension Organization by its UID if such organization does not exist yet + OFVector::iterator it = m_DimensionOrganizationSequence.begin(); + while (it != m_DimensionOrganizationSequence.end()) + { + OFString val; + (*it)->getDimensionOrganizationUID(val); + if (val == dimensionOrganizationUID) + { + break; + } + it++; + } + OFCondition result; + if (it == m_DimensionOrganizationSequence.end()) + { + DimensionOrganizationItem* item = new DimensionOrganizationItem; + if (item == NULL) + { + return EC_MemoryExhausted; + } + result = item->setDimensionOrganizationUID(dimensionOrganizationUID); + if (result.bad()) + return result; + m_DimensionOrganizationSequence.push_back(item); + } - result = dim->setDimensionOrganizationUID(dimensionOrganizationUID); - if (result.good()) result = dim->setFunctionalGroupPointer(functionalGroupPointer); - if (result.good()) result = dim->setDimensionIndexPointer(dimensionIndexPointer); - if (result.good() && !dimensionIndexPrivateCreator.empty()) dim->setDimensionIndexPrivateCreator(dimensionIndexPrivateCreator); - if (result.good() && !functionalGroupPrivateCreator.empty()) dim->setFunctionalGroupPrivateCreator(functionalGroupPrivateCreator); - if (result.good() && !dimensionDescriptionLabel.empty()) dim->setDimensionDescriptionLabel(dimensionDescriptionLabel); - if (result.bad()) - { - DCMIOD_ERROR("Could not add Dimension Index: Invalid data values"); - delete dim; - } - m_DimensionIndexSequence.push_back(dim); + // Create dimension and add it to this object + DimensionIndexItem* dim = new DimensionIndexItem(); + if (!dim) + return EC_MemoryExhausted; + + result = dim->setDimensionOrganizationUID(dimensionOrganizationUID); + if (result.good()) + result = dim->setFunctionalGroupPointer(functionalGroupPointer); + if (result.good()) + result = dim->setDimensionIndexPointer(dimensionIndexPointer); + if (result.good() && !dimensionIndexPrivateCreator.empty()) + dim->setDimensionIndexPrivateCreator(dimensionIndexPrivateCreator); + if (result.good() && !functionalGroupPrivateCreator.empty()) + dim->setFunctionalGroupPrivateCreator(functionalGroupPrivateCreator); + if (result.good() && !dimensionDescriptionLabel.empty()) + dim->setDimensionDescriptionLabel(dimensionDescriptionLabel); + if (result.bad()) + { + DCMIOD_ERROR("Could not add Dimension Index: Invalid data values"); + delete dim; + } + m_DimensionIndexSequence.push_back(dim); - return result; + return result; } - OFString IODMultiframeDimensionModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODMultiframeDimensionModule::clearData() { - DcmIODUtil::freeContainer(m_DimensionIndexSequence); - IODComponent::clearData(); + DcmIODUtil::freeContainer(m_DimensionIndexSequence); + IODComponent::clearData(); } - - -OFCondition IODMultiframeDimensionModule::read(DcmItem& source, - const OFBool clearOldData) +OFCondition IODMultiframeDimensionModule::read(DcmItem& source, const OFBool clearOldData) { - if (clearOldData) - clearData(); + if (clearOldData) + clearData(); - IODComponent::read(source, OFFalse /* data already cleared above */); + IODComponent::read(source, OFFalse /* data already cleared above */); - DcmIODUtil::readSubSequence(source, DCM_DimensionIndexSequence, m_DimensionIndexSequence, m_Rules->getByTag(DCM_DimensionIndexSequence)); - DcmIODUtil::readSubSequence(source, DCM_DimensionOrganizationSequence, m_DimensionOrganizationSequence, m_Rules->getByTag(DCM_DimensionOrganizationSequence)); + DcmIODUtil::readSubSequence( + source, DCM_DimensionIndexSequence, m_DimensionIndexSequence, m_Rules->getByTag(DCM_DimensionIndexSequence)); + DcmIODUtil::readSubSequence(source, + DCM_DimensionOrganizationSequence, + m_DimensionOrganizationSequence, + m_Rules->getByTag(DCM_DimensionOrganizationSequence)); - return EC_Normal; + return EC_Normal; } - OFCondition IODMultiframeDimensionModule::write(DcmItem& destination) { - OFCondition result = EC_Normal; + OFCondition result = EC_Normal; - // Re-create dimension organization data - createDimensionOrganizationData(); - DcmIODUtil::writeSubSequence >(result, DCM_DimensionOrganizationSequence, m_DimensionOrganizationSequence, *m_Item, m_Rules->getByTag(DCM_DimensionOrganizationSequence)); + // Re-create dimension organization data + createDimensionOrganizationData(); + DcmIODUtil::writeSubSequence >( + result, + DCM_DimensionOrganizationSequence, + m_DimensionOrganizationSequence, + *m_Item, + m_Rules->getByTag(DCM_DimensionOrganizationSequence)); - DcmIODUtil::writeSubSequence >(result, DCM_DimensionIndexSequence, m_DimensionIndexSequence, *m_Item, m_Rules->getByTag(DCM_DimensionIndexSequence)); + DcmIODUtil::writeSubSequence >(result, + DCM_DimensionIndexSequence, + m_DimensionIndexSequence, + *m_Item, + m_Rules->getByTag(DCM_DimensionIndexSequence)); - result = IODComponent::write(destination); - return result; + result = IODComponent::write(destination); + return result; } - void IODMultiframeDimensionModule::resetRules() { - // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level - m_Rules->addRule(new IODRule(DCM_DimensionOrganizationSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionIndexSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionIndexSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); } - OFCondition IODMultiframeDimensionModule::checkDimensions(DcmItem* fgItem) { - if (fgItem == NULL) - { - fgItem = &getData(); - } - - DcmSequenceOfItems *perFrame = NULL; - if (fgItem->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame).bad()) - { - DCMIOD_WARN("Will not check dimension consistency with functional groups (no per-frame functional groups found)"); - } - - OFCondition result; - OFVector::iterator dim = m_DimensionIndexSequence.begin(); - size_t errors = 0; - size_t dimNo = 1; - while (dim != m_DimensionIndexSequence.end()) - { - DcmTagKey indexPointer; - result = (*dim)->getDimensionIndexPointer(indexPointer); - if (result.bad()) + if (fgItem == NULL) { - DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension index pointer"); - errors++; + fgItem = &getData(); } - OFString uid; - result = (*dim)->getDimensionOrganizationUID(uid); - if (result.bad()) - { - DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension organization UID"); - errors++; - } - DcmTagKey fgPointer; - result = (*dim)->getFunctionalGroupPointer(fgPointer); - if (result.bad()) - { - DCMIOD_ERROR("Dimension " << dimNo << " does not provide a functional group pointer"); - errors++; - } - OFString privateCreator; - if (indexPointer.isPrivate() && (indexPointer != DCM_UndefinedTagKey) ) - { - result = (*dim)->getDimensionIndexPrivateCreator(privateCreator); - if (result.bad()) - { - DCMIOD_ERROR("Dimension " << dimNo << " has private index pointer " << indexPointer << " but private creator is not set"); - errors++; - } - } - OFString privateFGCreator; - if (fgPointer.isPrivate() && (fgPointer != DCM_UndefinedTagKey)) + + DcmSequenceOfItems* perFrame = NULL; + if (fgItem->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame).bad()) { - result = (*dim)->getFunctionalGroupPrivateCreator(privateFGCreator); - if (result.bad()) - { - DCMIOD_ERROR("Dimension " << dimNo << " has private fg group pointer " << fgPointer << " but private creator is not set"); - errors++; - } + DCMIOD_WARN( + "Will not check dimension consistency with functional groups (no per-frame functional groups found)"); } - if (perFrame && (fgPointer != DCM_UndefinedTagKey) && (indexPointer != DCM_UndefinedTagKey) ) + OFCondition result; + OFVector::iterator dim = m_DimensionIndexSequence.begin(); + size_t errors = 0; + size_t dimNo = 1; + while (dim != m_DimensionIndexSequence.end()) { - if (!getIndexElement(perFrame, fgPointer, indexPointer, privateFGCreator, privateCreator)) - { - errors++; - } - } + DcmTagKey indexPointer; + result = (*dim)->getDimensionIndexPointer(indexPointer); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension index pointer"); + errors++; + } + OFString uid; + result = (*dim)->getDimensionOrganizationUID(uid); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension organization UID"); + errors++; + } + DcmTagKey fgPointer; + result = (*dim)->getFunctionalGroupPointer(fgPointer); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a functional group pointer"); + errors++; + } + OFString privateCreator; + if (indexPointer.isPrivate() && (indexPointer != DCM_UndefinedTagKey)) + { + result = (*dim)->getDimensionIndexPrivateCreator(privateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " has private index pointer " << indexPointer + << " but private creator is not set"); + errors++; + } + } + OFString privateFGCreator; + if (fgPointer.isPrivate() && (fgPointer != DCM_UndefinedTagKey)) + { + result = (*dim)->getFunctionalGroupPrivateCreator(privateFGCreator); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " has private fg group pointer " << fgPointer + << " but private creator is not set"); + errors++; + } + } + + if (perFrame && (fgPointer != DCM_UndefinedTagKey) && (indexPointer != DCM_UndefinedTagKey)) + { + if (!getIndexElement(perFrame, fgPointer, indexPointer, privateFGCreator, privateCreator)) + { + errors++; + } + } - dim++; - } + dim++; + } - if (errors > 0) - return IOD_EC_InvalidDimensions; - else - return EC_Normal; + if (errors > 0) + return IOD_EC_InvalidDimensions; + else + return EC_Normal; } - -DcmElement* IODMultiframeDimensionModule::getIndexElement(DcmSequenceOfItems *perFrameFG, +DcmElement* IODMultiframeDimensionModule::getIndexElement(DcmSequenceOfItems* perFrameFG, const DcmTagKey& fgPointer, const DcmTagKey& indexPointer, - const OFString& fgPrivateCreator, - const OFString& privateCreator) -{ - if (perFrameFG == NULL) - { - DCMIOD_ERROR("Cannot get Dimension Index: No per-frame functional groups are provided"); - return NULL; // nothing to do - } - - size_t numFrames = perFrameFG->card(); - OFCondition result; - DcmElement *returnValue = NULL; - for (size_t count = 0; count < numFrames; count++) - { - DcmItem* item = perFrameFG->getItem(OFstatic_cast(unsigned long, count)); - if (item != NULL) + const OFString& fgPrivateCreator, + const OFString& privateCreator) +{ + if (perFrameFG == NULL) { - // Check for the functional group mentioned in dimension - DcmSequenceOfItems *fgSequence = NULL; - if (item->findAndGetSequence(fgPointer, fgSequence).good()) - { - // Check private reservation for fg if necessary - if (fgPointer.isPrivate()) - { - result = DcmPathProcessor::checkPrivateTagReservation(item, fgPointer, fgPrivateCreator); - if (result.bad()) - { - DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " << result.text()); - } - } - // Check whether actual fg information exists (single item in related fg sequence) - DcmItem *fgItem = fgSequence->getItem(0); - if (fgItem != NULL) + DCMIOD_ERROR("Cannot get Dimension Index: No per-frame functional groups are provided"); + return NULL; // nothing to do + } + + size_t numFrames = perFrameFG->card(); + OFCondition result; + DcmElement* returnValue = NULL; + for (size_t count = 0; count < numFrames; count++) + { + DcmItem* item = perFrameFG->getItem(OFstatic_cast(unsigned long, count)); + if (item != NULL) { - if (fgItem->findAndGetElement(indexPointer, returnValue).good()) - { - if (returnValue->getTag().isPrivate()) + // Check for the functional group mentioned in dimension + DcmSequenceOfItems* fgSequence = NULL; + if (item->findAndGetSequence(fgPointer, fgSequence).good()) { - if (!privateCreator.empty()) - { - result = DcmPathProcessor::checkPrivateTagReservation(fgItem, indexPointer, privateCreator); - if (result.bad()) + // Check private reservation for fg if necessary + if (fgPointer.isPrivate()) + { + result = DcmPathProcessor::checkPrivateTagReservation(item, fgPointer, fgPrivateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " << result.text()); + } + } + // Check whether actual fg information exists (single item in related fg sequence) + DcmItem* fgItem = fgSequence->getItem(0); + if (fgItem != NULL) { - DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " << result.text()); + if (fgItem->findAndGetElement(indexPointer, returnValue).good()) + { + if (returnValue->getTag().isPrivate()) + { + if (!privateCreator.empty()) + { + result = DcmPathProcessor::checkPrivateTagReservation( + fgItem, indexPointer, privateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " + << result.text()); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " + << fgPointer << " misses reservation for frame " << count << ": " + << result.text()); + } + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " + << fgPointer << " does not contain index pointer attribute " << indexPointer + << " for frame " << count); + } } - } - else - { - DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " misses reservation for frame " << count << ": " << result.text()); - } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does have any data for frame " + << count); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does not exist for frame " + << count); } - } - else - { - DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does not contain index pointer attribute " << indexPointer << " for frame " << count); - } } else { - DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does have any data for frame " << count); + DCMIOD_ERROR("Cannot get Dimension Index: since no per-frame functional group for frame " << count + << " exists"); } - } - else - { - DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does not exist for frame " << count); - } - } - else - { - DCMIOD_ERROR("Cannot get Dimension Index: since no per-frame functional group for frame " << count << " exists"); } - } - return returnValue; + return returnValue; } - - void IODMultiframeDimensionModule::createDimensionOrganizationData() { - // Clear old data - DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); - // Collect dimensions from all Dimension Index Pointers - OFVector::iterator item = m_DimensionIndexSequence.begin(); - while (item != m_DimensionIndexSequence.end()) - { - OFCondition result; - // Make sure every UID is only added once - OFBool isNew = OFTrue; - OFString existinguid, newuid; - (*item)->getDimensionOrganizationUID(newuid); - OFVector::iterator existing = m_DimensionOrganizationSequence.begin(); - while (existing != m_DimensionOrganizationSequence.end()) - { - (*existing)->getDimensionOrganizationUID(existinguid); - if (existinguid == newuid) - { - isNew = OFFalse; - break; - } - existing++; - } - if (isNew) + // Clear old data + DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); + // Collect dimensions from all Dimension Index Pointers + OFVector::iterator item = m_DimensionIndexSequence.begin(); + while (item != m_DimensionIndexSequence.end()) { - DimensionOrganizationItem* uidItem = new DimensionOrganizationItem(); - if (!uidItem) - { - DCMIOD_ERROR("Memory Exhausted while collecting Dimension Organziation UIDs"); - return; - } - result = uidItem->setDimensionOrganizationUID(newuid); - if (result.good()) - { - m_DimensionOrganizationSequence.push_back(uidItem); - } - else - { - DCMIOD_ERROR("Could not set Dimension Organization UID " << newuid << ": " << result.text()); - delete uidItem; - return; - } + OFCondition result; + // Make sure every UID is only added once + OFBool isNew = OFTrue; + OFString existinguid, newuid; + (*item)->getDimensionOrganizationUID(newuid); + OFVector::iterator existing = m_DimensionOrganizationSequence.begin(); + while (existing != m_DimensionOrganizationSequence.end()) + { + (*existing)->getDimensionOrganizationUID(existinguid); + if (existinguid == newuid) + { + isNew = OFFalse; + break; + } + existing++; + } + if (isNew) + { + DimensionOrganizationItem* uidItem = new DimensionOrganizationItem(); + if (!uidItem) + { + DCMIOD_ERROR("Memory Exhausted while collecting Dimension Organziation UIDs"); + return; + } + result = uidItem->setDimensionOrganizationUID(newuid); + if (result.good()) + { + m_DimensionOrganizationSequence.push_back(uidItem); + } + else + { + DCMIOD_ERROR("Could not set Dimension Organization UID " << newuid << ": " << result.text()); + delete uidItem; + return; + } + } + item++; } - item++; - } } - -OFCondition IODMultiframeDimensionModule::getDimensionOrganizationType(OFString& value, - const long signed int pos) const +OFCondition IODMultiframeDimensionModule::getDimensionOrganizationType(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); } - -OFCondition IODMultiframeDimensionModule::setDimensionOrganizationType(const OFString& value, - const OFBool checkValue) +OFCondition IODMultiframeDimensionModule::setDimensionOrganizationType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); + return result; } - -OFVector< IODMultiframeDimensionModule::DimensionIndexItem* >& IODMultiframeDimensionModule::getDimensionIndexSequence() +OFVector& IODMultiframeDimensionModule::getDimensionIndexSequence() { - return m_DimensionIndexSequence; + return m_DimensionIndexSequence; } -OFVector< IODMultiframeDimensionModule::DimensionOrganizationItem* >& IODMultiframeDimensionModule::getDimensionOrganizationSequence() +OFVector& +IODMultiframeDimensionModule::getDimensionOrganizationSequence() { - return m_DimensionOrganizationSequence; + return m_DimensionOrganizationSequence; } IODMultiframeDimensionModule::~IODMultiframeDimensionModule() { - DcmIODUtil::freeContainer(m_DimensionIndexSequence); - DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); + DcmIODUtil::freeContainer(m_DimensionIndexSequence); + DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); } - IODMultiframeDimensionModule::DimensionIndexItem::DimensionIndexItem(OFshared_ptr data, - OFshared_ptr rules, - IODComponent* parent) -: IODComponent(data, rules, parent) + OFshared_ptr rules, + IODComponent* parent) + : IODComponent(data, rules, parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } -IODMultiframeDimensionModule::DimensionIndexItem::DimensionIndexItem(IODComponent* parent): -IODComponent(parent) +IODMultiframeDimensionModule::DimensionIndexItem::DimensionIndexItem(IODComponent* parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODMultiframeDimensionModule::DimensionIndexItem::~DimensionIndexItem() { - // Nothing to do + // Nothing to do } - void IODMultiframeDimensionModule::DimensionIndexItem::resetRules() { - // Concatenation attributes - m_Rules->addRule(new IODRule(DCM_DimensionIndexPointer, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionIndexPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_FunctionalGroupPointer, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_FunctionalGroupPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_DimensionDescriptionLabel, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_DimensionIndexPointer, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionIndexPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_FunctionalGroupPointer, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_FunctionalGroupPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionDescriptionLabel, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), + OFTrue); } - OFString IODMultiframeDimensionModule::DimensionIndexItem::getName() const { - return "DimensionIndexSequence"; + return "DimensionIndexSequence"; } - -OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionDescriptionLabel(OFString& value, - const long signed int pos) const +OFCondition +IODMultiframeDimensionModule::DimensionIndexItem::getDimensionDescriptionLabel(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionDescriptionLabel, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionDescriptionLabel, *m_Item, value, pos); } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionIndexPointer(DcmTagKey& value, - const long signed int pos) const -{ - OFString tagstr; - DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPointer, *m_Item, tagstr, pos); - value = DcmIODUtil::parseTagKey(tagstr); - if (value == DCM_UndefinedTagKey) - return EC_TagNotFound; - else - return EC_Normal; + const long signed int pos) const +{ + OFString tagstr; + DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPointer, *m_Item, tagstr, pos); + value = DcmIODUtil::parseTagKey(tagstr); + if (value == DCM_UndefinedTagKey) + return EC_TagNotFound; + else + return EC_Normal; } - -OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionIndexPrivateCreator(OFString& value, - const long signed int pos) const +OFCondition +IODMultiframeDimensionModule::DimensionIndexItem::getDimensionIndexPrivateCreator(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPrivateCreator, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPrivateCreator, *m_Item, value, pos); } - -OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionOrganizationUID(OFString& value, - const long signed int pos) const +OFCondition +IODMultiframeDimensionModule::DimensionIndexItem::getDimensionOrganizationUID(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getFunctionalGroupPointer(DcmTagKey& value, - const long signed int pos) const -{ - OFString tagstr; - DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPointer, *m_Item, tagstr, pos); - value = DcmIODUtil::parseTagKey(tagstr); - if (value == DCM_UndefinedTagKey) - return EC_TagNotFound; - else - return EC_Normal; + const long signed int pos) const +{ + OFString tagstr; + DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPointer, *m_Item, tagstr, pos); + value = DcmIODUtil::parseTagKey(tagstr); + if (value == DCM_UndefinedTagKey) + return EC_TagNotFound; + else + return EC_Normal; } - -OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getFunctionalGroupPrivateCreator(OFString& value, - const long signed int pos) const +OFCondition +IODMultiframeDimensionModule::DimensionIndexItem::getFunctionalGroupPrivateCreator(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPrivateCreator, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPrivateCreator, *m_Item, value, pos); } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionDescriptionLabel(const OFString& value, - const OFBool checkValue) + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DimensionDescriptionLabel, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionDescriptionLabel, value); + return result; } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setFunctionalGroupPointer(const DcmTagKey& value, const OFBool checkValue) { - (void)checkValue; - if (value == DCM_UndefinedTagKey) - return EC_IllegalParameter; + (void)checkValue; + if (value == DCM_UndefinedTagKey) + return EC_IllegalParameter; - DcmAttributeTag *elem = OFstatic_cast(DcmAttributeTag*, DcmItem::newDicomElement(DCM_FunctionalGroupPointer)); - if (elem == NULL) - return EC_InternalError; + DcmAttributeTag* elem = OFstatic_cast(DcmAttributeTag*, DcmItem::newDicomElement(DCM_FunctionalGroupPointer)); + if (elem == NULL) + return EC_InternalError; - OFCondition result; - Uint16 *attrTagArray; - result = elem->putTagVal(value); - if (result.good()) result = elem->getUint16Array(attrTagArray); - if (result.good()) result = m_Item->putAndInsertUint16Array(DCM_FunctionalGroupPointer, attrTagArray, 1); - delete elem; + OFCondition result; + Uint16* attrTagArray; + result = elem->putTagVal(value); + if (result.good()) + result = elem->getUint16Array(attrTagArray); + if (result.good()) + result = m_Item->putAndInsertUint16Array(DCM_FunctionalGroupPointer, attrTagArray, 1); + delete elem; - return result; + return result; } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setFunctionalGroupPrivateCreator(const OFString& value, - const OFBool checkValue) + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_FunctionalGroupPrivateCreator, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_FunctionalGroupPrivateCreator, value); + return result; } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionIndexPointer(const DcmTagKey& value, const OFBool checkValue) { - (void)checkValue; - if (value == DCM_UndefinedTagKey) - return EC_IllegalParameter; + (void)checkValue; + if (value == DCM_UndefinedTagKey) + return EC_IllegalParameter; - DcmAttributeTag *elem = OFstatic_cast(DcmAttributeTag*, DcmItem::newDicomElement(DCM_DimensionIndexPointer)); - if (elem == NULL) - return EC_InternalError; + DcmAttributeTag* elem = OFstatic_cast(DcmAttributeTag*, DcmItem::newDicomElement(DCM_DimensionIndexPointer)); + if (elem == NULL) + return EC_InternalError; - OFCondition result; - Uint16 *attrTagArray; - result = elem->putTagVal(value); - if (result.good()) result = elem->getUint16Array(attrTagArray); - if (result.good()) result = m_Item->putAndInsertUint16Array(DCM_DimensionIndexPointer, attrTagArray, 1); - delete elem; + OFCondition result; + Uint16* attrTagArray; + result = elem->putTagVal(value); + if (result.good()) + result = elem->getUint16Array(attrTagArray); + if (result.good()) + result = m_Item->putAndInsertUint16Array(DCM_DimensionIndexPointer, attrTagArray, 1); + delete elem; - return result; + return result; } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionIndexPrivateCreator(const OFString& value, - const OFBool checkValue) + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DimensionIndexPrivateCreator, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionIndexPrivateCreator, value); + return result; } - OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionOrganizationUID(const OFString& value, - const OFBool checkValue) + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); + return result; } - - // -- Dimension Organization Sequence Item -- IODMultiframeDimensionModule::DimensionOrganizationItem::DimensionOrganizationItem(OFshared_ptr data, OFshared_ptr rules, IODComponent* parent) -: IODComponent(data, rules, parent) + : IODComponent(data, rules, parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } IODMultiframeDimensionModule::DimensionOrganizationItem::DimensionOrganizationItem(IODComponent* parent) -: IODComponent(parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODMultiframeDimensionModule::DimensionOrganizationItem::~DimensionOrganizationItem() { - // Nothing to do + // Nothing to do } - void IODMultiframeDimensionModule::DimensionOrganizationItem::resetRules() { - // Concatenation attributes - m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); } - OFString IODMultiframeDimensionModule::DimensionOrganizationItem::getName() const { - return "DimensionOrganizationSequence"; + return "DimensionOrganizationSequence"; } -OFCondition IODMultiframeDimensionModule::DimensionOrganizationItem::getDimensionOrganizationUID(OFString& value, - const long signed int pos) const +OFCondition +IODMultiframeDimensionModule::DimensionOrganizationItem::getDimensionOrganizationUID(OFString& value, + const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); } - -OFCondition IODMultiframeDimensionModule::DimensionOrganizationItem::setDimensionOrganizationUID(const OFString& value, const OFBool checkValue) +OFCondition +IODMultiframeDimensionModule::DimensionOrganizationItem::setDimensionOrganizationUID(const OFString& value, + const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); + return result; } diff --git a/dcmiod/libsrc/modmultiframefg.cc b/dcmiod/libsrc/modmultiframefg.cc index b706fb94..fac6ec7c 100644 --- a/dcmiod/libsrc/modmultiframefg.cc +++ b/dcmiod/libsrc/modmultiframefg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,272 +19,245 @@ * */ -#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmiod/modmultiframefg.h" -#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcvrda.h" -#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" // for static helpers const OFString IODMultiFrameFGModule::m_ModuleName = "MultiframeFunctionalGroupsModule"; - -IODMultiFrameFGModule::IODMultiFrameFGModule(OFshared_ptr data, - OFshared_ptr rules) -: IODModule(data, rules), - m_ConcatenationInfo(data, rules) +IODMultiFrameFGModule::IODMultiFrameFGModule(OFshared_ptr data, OFshared_ptr rules) + : IODModule(data, rules) + , m_ConcatenationInfo(data, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODMultiFrameFGModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODMultiFrameFGModule::IODMultiFrameFGModule() -: IODModule(), - m_ConcatenationInfo() + : IODModule() + , m_ConcatenationInfo() { - resetRules(); + resetRules(); } - void IODMultiFrameFGModule::resetRules() { - m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_NumberOfFrames, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_RepresentativeFrameNumber, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_ConcatenationInfo.resetRules(); + m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_NumberOfFrames, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RepresentativeFrameNumber, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_ConcatenationInfo.resetRules(); } - IODMultiFrameFGModule::~IODMultiFrameFGModule() { } - -IODMultiFrameFGModule::ConcatenationInfo& IODMultiFrameFGModule::getConcatenationInfo() +OFCondition IODMultiFrameFGModule::read(DcmItem& source, const bool clearOldData) { - return m_ConcatenationInfo; + IODModule::read(source, clearOldData); + m_ConcatenationInfo.read(source, clearOldData); + return EC_Normal; } - -OFCondition IODMultiFrameFGModule::getInstanceNumber(Sint32& value, - const unsigned int pos) +OFCondition IODMultiFrameFGModule::write(DcmItem& destination) { - return m_Item->findAndGetSint32(DCM_InstanceNumber, value, pos); + OFCondition result = IODModule::write(destination); + if (result.good()) + m_ConcatenationInfo.write(destination); + return result; } - -OFCondition IODMultiFrameFGModule::getContentDate(OFString& value, - const long signed int pos) +IODMultiFrameFGModule::ConcatenationInfo& IODMultiFrameFGModule::getConcatenationInfo() { - return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); + return m_ConcatenationInfo; } - -OFCondition IODMultiFrameFGModule::getContentTime(OFString& value, - const long signed int pos) +OFCondition IODMultiFrameFGModule::getInstanceNumber(Sint32& value, const unsigned int pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); + return m_Item->findAndGetSint32(DCM_InstanceNumber, value, pos); } - -OFCondition IODMultiFrameFGModule::getNumberOfFrames(Sint32& value, - const unsigned int pos) +OFCondition IODMultiFrameFGModule::getContentDate(OFString& value, const long signed int pos) { - return m_Item->findAndGetSint32(DCM_NumberOfFrames, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); } +OFCondition IODMultiFrameFGModule::getContentTime(OFString& value, const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); +} -OFCondition IODMultiFrameFGModule::getRepresentativeFrameNumber(Uint16& value, - const unsigned int pos) +OFCondition IODMultiFrameFGModule::getNumberOfFrames(Sint32& value, const unsigned int pos) { - return m_Item->findAndGetUint16(DCM_RepresentativeFrameNumber, value, pos); + return m_Item->findAndGetSint32(DCM_NumberOfFrames, value, pos); } +OFCondition IODMultiFrameFGModule::getRepresentativeFrameNumber(Uint16& value, const unsigned int pos) +{ + return m_Item->findAndGetUint16(DCM_RepresentativeFrameNumber, value, pos); +} // -- setters -- - -OFCondition IODMultiFrameFGModule::setConcatenationInfo(const IODMultiFrameFGModule::ConcatenationInfo& concatenationInfo) +OFCondition +IODMultiFrameFGModule::setConcatenationInfo(const IODMultiFrameFGModule::ConcatenationInfo& concatenationInfo) { - m_ConcatenationInfo = concatenationInfo; - return EC_Normal; + m_ConcatenationInfo = concatenationInfo; + return EC_Normal; } - -OFCondition IODMultiFrameFGModule::setInstanceNumber(const OFString& value, - const OFBool checkValue) +OFCondition IODMultiFrameFGModule::setInstanceNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); + return result; } - -OFCondition IODMultiFrameFGModule::setContentDate(const OFString& value, - const OFBool checkValue) +OFCondition IODMultiFrameFGModule::setContentDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); + return result; } - -OFCondition IODMultiFrameFGModule::setContentTime(const OFString& value, - const OFBool checkValue) +OFCondition IODMultiFrameFGModule::setContentTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); + return result; } - OFCondition IODMultiFrameFGModule::setNumberOfFrames(const Uint32 value) { - if (value > 2147483647) - { - DCMIOD_ERROR("Cannot set Number of Frames to " << value << ": Maximum permitted value is 2147483647"); - return EC_InvalidValue; - } - OFCondition result; - OFStringStream oss; - oss << value; - OFSTRINGSTREAM_GETSTR(oss,tempstr); - result = m_Item->putAndInsertOFStringArray(DCM_NumberOfFrames, tempstr); - OFSTRINGSTREAM_FREESTR(tmpstr); - return result; + if (value > 2147483647) + { + DCMIOD_ERROR("Cannot set Number of Frames to " << value << ": Maximum permitted value is 2147483647"); + return EC_InvalidValue; + } + OFCondition result; + OFStringStream oss; + oss << value; + OFSTRINGSTREAM_GETSTR(oss, tempstr); + result = m_Item->putAndInsertOFStringArray(DCM_NumberOfFrames, tempstr); + OFSTRINGSTREAM_FREESTR(tmpstr); + return result; } - OFCondition IODMultiFrameFGModule::setRepresentativeFrameNumber(const Uint16 value) { - return m_Item->putAndInsertUint16(DCM_RepresentativeFrameNumber, value); + return m_Item->putAndInsertUint16(DCM_RepresentativeFrameNumber, value); } - -IODMultiFrameFGModule::ConcatenationInfo::ConcatenationInfo(OFshared_ptr data, - OFshared_ptr rules) -: IODComponent(data, rules) +IODMultiFrameFGModule::ConcatenationInfo::ConcatenationInfo(OFshared_ptr data, OFshared_ptr rules) + : IODComponent(data, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODMultiFrameFGModule::ConcatenationInfo::ConcatenationInfo(IODComponent* parent) -: IODComponent(parent) + : IODComponent(parent) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODMultiFrameFGModule::ConcatenationInfo::~ConcatenationInfo() { - // Nothing to do + // Nothing to do } - OFString IODMultiFrameFGModule::ConcatenationInfo::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODMultiFrameFGModule::ConcatenationInfo::resetRules() { - // Concatenation attributes - m_Rules->addRule(new IODRule(DCM_ConcatenationFrameOffsetNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_ConcatenationUID, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_SOPInstanceUIDOfConcatenationSource, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_InConcatenationNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_InConcatenationTotalNumber, "1", "3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_ConcatenationFrameOffsetNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_ConcatenationUID, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule( + new IODRule(DCM_SOPInstanceUIDOfConcatenationSource, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), + OFTrue); + m_Rules->addRule(new IODRule(DCM_InConcatenationNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InConcatenationTotalNumber, "1", "3", m_ModuleName, DcmIODTypes::IE_INSTANCE), + OFTrue); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::getConcatenationFrameOffsetNumber(Uint32& value, - const unsigned int pos) + const unsigned int pos) { - return m_Item->findAndGetUint32(DCM_ConcatenationFrameOffsetNumber, value, pos); + return m_Item->findAndGetUint32(DCM_ConcatenationFrameOffsetNumber, value, pos); } - -OFCondition IODMultiFrameFGModule::ConcatenationInfo::getConcatenationUID(OFString& value, - const signed long pos) +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getConcatenationUID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_ConcatenationUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_ConcatenationUID, *m_Item, value, pos); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::getSOPInstanceUIDOfConcatenationSource(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUIDOfConcatenationSource, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUIDOfConcatenationSource, *m_Item, value, pos); } - -OFCondition IODMultiFrameFGModule::ConcatenationInfo::getInConcatenationNumber(Uint16& value, - const unsigned int pos) +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getInConcatenationNumber(Uint16& value, const unsigned int pos) { - return m_Item->findAndGetUint16(DCM_InConcatenationNumber, value, pos); + return m_Item->findAndGetUint16(DCM_InConcatenationNumber, value, pos); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::getInConcatenationTotalNumber(Uint16& value, const unsigned int pos) { - return m_Item->findAndGetUint16(DCM_InConcatenationTotalNumber, value, pos); + return m_Item->findAndGetUint16(DCM_InConcatenationTotalNumber, value, pos); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::setConcatenationFrameOffsetNumber(const Uint32 value) { - return m_Item->putAndInsertUint32(DCM_ConcatenationFrameOffsetNumber, value); + return m_Item->putAndInsertUint32(DCM_ConcatenationFrameOffsetNumber, value); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::setConcatenationUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_ConcatenationUID, value); - return result; - + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ConcatenationUID, value); + return result; } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::setSOPInstanceUIDOfConcatenationSource(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, value); - return result; - + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, value); + return result; } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::setInConcatenationNumber(const Uint16 value) { - return m_Item->putAndInsertUint16(DCM_InConcatenationNumber, value); + return m_Item->putAndInsertUint16(DCM_InConcatenationNumber, value); } - OFCondition IODMultiFrameFGModule::ConcatenationInfo::setInConcatenationTotalNumber(const Uint16 value) { - return m_Item->putAndInsertUint16(DCM_InConcatenationTotalNumber, value); + return m_Item->putAndInsertUint16(DCM_InConcatenationTotalNumber, value); } diff --git a/dcmiod/libsrc/modpatient.cc b/dcmiod/libsrc/modpatient.cc index 48013f5a..82152e92 100644 --- a/dcmiod/libsrc/modpatient.cc +++ b/dcmiod/libsrc/modpatient.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,118 +19,95 @@ * */ - -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modpatient.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODPatientModule::m_ModuleName = "PatientModule"; - -IODPatientModule::IODPatientModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODPatientModule::IODPatientModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - OFString IODPatientModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODPatientModule::IODPatientModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODPatientModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_PatientName, "1","2",getName(), DcmIODTypes::IE_PATIENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientID, "1","2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientBirthDate, "1","2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientSex, "1","2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_PatientName, "1", "2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientID, "1", "2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientBirthDate, "1", "2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientSex, "1", "2", getName(), DcmIODTypes::IE_PATIENT), OFTrue); } - IODPatientModule::~IODPatientModule() { } - // --- get attributes (C++ string) --- - -OFCondition IODPatientModule::getPatientName(OFString &value, - const signed long pos) const +OFCondition IODPatientModule::getPatientName(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientName, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientName, *m_Item, value, pos); } - -OFCondition IODPatientModule::getPatientBirthDate(OFString &value, - const signed long pos) const +OFCondition IODPatientModule::getPatientBirthDate(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientBirthDate, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientBirthDate, *m_Item, value, pos); } - -OFCondition IODPatientModule::getPatientSex(OFString &value, - const signed long pos) const +OFCondition IODPatientModule::getPatientSex(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientSex, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientSex, *m_Item, value, pos); } -OFCondition IODPatientModule::getPatientID(OFString &value, - const signed long pos) const +OFCondition IODPatientModule::getPatientID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientID, *m_Item, value, pos); } // --- set attributes --- -OFCondition IODPatientModule::setPatientName(const OFString &value, - const OFBool checkValue) +OFCondition IODPatientModule::setPatientName(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientName, value); - return result; + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientName, value); + return result; } - -OFCondition IODPatientModule::setPatientID(const OFString &value, - const OFBool checkValue) +OFCondition IODPatientModule::setPatientID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientID, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientID, value); + return result; } - -OFCondition IODPatientModule::setPatientBirthDate(const OFString &value, - const OFBool checkValue) +OFCondition IODPatientModule::setPatientBirthDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientBirthDate, value); - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientBirthDate, value); + return result; } - -OFCondition IODPatientModule::setPatientSex(const OFString &value, - const OFBool checkValue) +OFCondition IODPatientModule::setPatientSex(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientSex, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientSex, value); + return result; } - diff --git a/dcmiod/libsrc/modpatientstudy.cc b/dcmiod/libsrc/modpatientstudy.cc index d87b22c9..b7af015c 100644 --- a/dcmiod/libsrc/modpatientstudy.cc +++ b/dcmiod/libsrc/modpatientstudy.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,116 +19,95 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modpatientstudy.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODPatientStudyModule::m_ModuleName = "PatientStudyModule"; - -IODPatientStudyModule::IODPatientStudyModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODPatientStudyModule::IODPatientStudyModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - resetRules(); + resetRules(); } - OFString IODPatientStudyModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODPatientStudyModule::IODPatientStudyModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODPatientStudyModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_AdmittingDiagnosesDescription, "1-n","3",getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientAge, "1","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientSize, "1","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientWeight, "1","3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_AdmittingDiagnosesDescription, "1-n", "3", getName(), DcmIODTypes::IE_STUDY), + OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientAge, "1", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientSize, "1", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientWeight, "1", "3", getName(), DcmIODTypes::IE_STUDY), OFTrue); } - IODPatientStudyModule::~IODPatientStudyModule() { } - // --- get attributes (C++ string) --- -OFCondition IODPatientStudyModule::getAdmittingDiagnosesDescription(OFString& value, - const signed long pos) const +OFCondition IODPatientStudyModule::getAdmittingDiagnosesDescription(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_AdmittingDiagnosesDescription, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AdmittingDiagnosesDescription, *m_Item, value, pos); } - -OFCondition IODPatientStudyModule::getPatientAge(OFString& value, - const signed long pos) const +OFCondition IODPatientStudyModule::getPatientAge(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_PatientAge, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientAge, *m_Item, value, pos); } - -OFCondition IODPatientStudyModule::getPatientWeight(Float64& value, - const unsigned long pos) const +OFCondition IODPatientStudyModule::getPatientWeight(Float64& value, const unsigned long pos) const { - return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientWeight, *m_Item, value, pos); + return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientWeight, *m_Item, value, pos); } - -OFCondition IODPatientStudyModule::getPatientSize(Float64& value, - const unsigned long pos) const +OFCondition IODPatientStudyModule::getPatientSize(Float64& value, const unsigned long pos) const { - return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientSize, *m_Item, value, pos); + return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientSize, *m_Item, value, pos); } - // --- set attributes --- - -OFCondition IODPatientStudyModule::setAdmittingDiagnosesDescription(const OFString& value, - const OFBool checkValue) +OFCondition IODPatientStudyModule::setAdmittingDiagnosesDescription(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_AdmittingDiagnosesDescription, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AdmittingDiagnosesDescription, value); + return result; } -OFCondition IODPatientStudyModule::setPatientAge(const OFString& value, - const OFBool checkValue) +OFCondition IODPatientStudyModule::setPatientAge(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmAgeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientAge, value); - return result; + OFCondition result = (checkValue) ? DcmAgeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientAge, value); + return result; } - -OFCondition IODPatientStudyModule::setPatientSize(const OFString& value, - const OFBool checkValue) +OFCondition IODPatientStudyModule::setPatientSize(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientSize, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientSize, value); + return result; } - -OFCondition IODPatientStudyModule::setPatientWeight(const OFString& value, - const OFBool checkValue) +OFCondition IODPatientStudyModule::setPatientWeight(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientWeight, value); - return result; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientWeight, value); + return result; } diff --git a/dcmiod/libsrc/modsegmentationseries.cc b/dcmiod/libsrc/modsegmentationseries.cc index 4019fd11..92b39b95 100644 --- a/dcmiod/libsrc/modsegmentationseries.cc +++ b/dcmiod/libsrc/modsegmentationseries.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,129 +19,109 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modsegmentationseries.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/iodutil.h" const OFString IODSegmentationSeriesModule::m_ModuleName = "SegmentationSeriesModule"; - -IODSegmentationSeriesModule::IODSegmentationSeriesModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODSegmentationSeriesModule::IODSegmentationSeriesModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODSegmentationSeriesModule::IODSegmentationSeriesModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - IODSegmentationSeriesModule::~IODSegmentationSeriesModule() { } - OFString IODSegmentationSeriesModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - void IODSegmentationSeriesModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_Modality, "1","1", getName(), DcmIODTypes::IE_SERIES, "SEG"), OFTrue); - m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1","1", getName(), DcmIODTypes::IE_SERIES, "1"), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); - m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1","1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1", "1", getName(), DcmIODTypes::IE_SERIES, "SEG"), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1", "1", getName(), DcmIODTypes::IE_SERIES, "1"), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1", "1C", getName(), DcmIODTypes::IE_SERIES), OFTrue); } - -OFCondition IODSegmentationSeriesModule::getModality(OFString &value, - const signed long pos) const +OFCondition IODSegmentationSeriesModule::getModality(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); } - -OFCondition IODSegmentationSeriesModule::getSeriesNumber(OFString &value, - const signed long pos) const +OFCondition IODSegmentationSeriesModule::getSeriesNumber(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); } - -OFCondition IODSegmentationSeriesModule::getPPSSOPClassUID(OFString &value, - const signed long pos) const +OFCondition IODSegmentationSeriesModule::getPPSSOPClassUID(OFString& value, const signed long pos) const { - DcmItem *localItem = NULL; - OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); - if (result.good()) - { - result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *localItem, value, pos); - } - return result; + DcmItem* localItem = NULL; + OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *localItem, value, pos); + } + return result; } - -OFCondition IODSegmentationSeriesModule::getPPSSOPInstanceUID(OFString &value, - const signed long pos) const +OFCondition IODSegmentationSeriesModule::getPPSSOPInstanceUID(OFString& value, const signed long pos) const { - DcmItem *localItem = NULL; - OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); - if (result.good()) - { - result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *localItem, value, pos); - } - return result; + DcmItem* localItem = NULL; + OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *localItem, value, pos); + } + return result; } - -OFCondition IODSegmentationSeriesModule::setSeriesNumber(const OFString &value, - const OFBool checkValue) +OFCondition IODSegmentationSeriesModule::setSeriesNumber(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); - return result; + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); + return result; } - -OFCondition IODSegmentationSeriesModule::setPPSSOPClassUID(const OFString& value, - const OFBool checkValue) +OFCondition IODSegmentationSeriesModule::setPPSSOPClassUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - DcmItem *localItem = NULL; - result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; if (result.good()) { - result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); + DcmItem* localItem = NULL; + result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); + } } - } - return result; + return result; } - -OFCondition IODSegmentationSeriesModule::setPPSSOPInstanceUID(const OFString& value, - const OFBool checkValue) +OFCondition IODSegmentationSeriesModule::setPPSSOPInstanceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - DcmItem *localItem = NULL; - result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; if (result.good()) { - result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); + DcmItem* localItem = NULL; + result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); + } } - } - return result; + return result; } diff --git a/dcmiod/libsrc/modsopcommon.cc b/dcmiod/libsrc/modsopcommon.cc index 9ea9f074..a521d15d 100644 --- a/dcmiod/libsrc/modsopcommon.cc +++ b/dcmiod/libsrc/modsopcommon.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,228 +19,190 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modsopcommon.h" -#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcvrcs.h" -#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcvrda.h" -#include "dcmtk/dcmdata/dcvrtm.h" #include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" const OFString IODSOPCommonModule::m_ModuleName = "SOPCommonModule"; - -IODSOPCommonModule::IODSOPCommonModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODSOPCommonModule::IODSOPCommonModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODSOPCommonModule::IODSOPCommonModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODSOPCommonModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_SOPClassUID, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_SOPInstanceUID, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_SpecificCharacterSet, "1-n","1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstanceCreationDate, "1","3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstanceCreationTime, "1","3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_InstanceCreatorUID, "1","3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - m_Rules->addRule(new IODRule(DCM_TimezoneOffsetFromUTC, "1","3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); - + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SOPClassUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SOPInstanceUID, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SpecificCharacterSet, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreationDate, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreationTime, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreatorUID, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimezoneOffsetFromUTC, "1", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); } - OFString IODSOPCommonModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - - void IODSOPCommonModule::inventMissing() { - // SOP Instance UID - ensureInstanceUID(); + // SOP Instance UID + ensureInstanceUID(); - // All other attributes - IODComponent::inventMissing(); + // All other attributes + IODComponent::inventMissing(); } - IODSOPCommonModule::~IODSOPCommonModule() { } - void IODSOPCommonModule::ensureInstanceUID(const OFBool correctInvalid) { - OFString uidstr; + OFString uidstr; - /* create new sop instance UID if required */ - if (getSOPInstanceUID(uidstr).bad() || uidstr.empty() ) - { - setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); - } - else if (!uidstr.empty() && correctInvalid) - { - if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + /* create new sop instance UID if required */ + if (getSOPInstanceUID(uidstr).bad() || uidstr.empty()) + { + setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); + } + else if (!uidstr.empty() && correctInvalid) { - setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); } - } + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); + } + } } - - -OFCondition IODSOPCommonModule::getSpecificCharacterSet(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getSpecificCharacterSet(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SpecificCharacterSet, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SpecificCharacterSet, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getSOPInstanceUID(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getSOPInstanceUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUID, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getSOPClassUID(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getSOPClassUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SOPClassUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SOPClassUID, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getInstanceCreationDate(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getInstanceCreationDate(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationDate, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationDate, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getInstanceCreationTime(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getInstanceCreationTime(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationTime, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationTime, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getInstanceCreatorUID(OFString &value, - const signed long pos) const +OFCondition IODSOPCommonModule::getInstanceCreatorUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreatorUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreatorUID, *m_Item, value, pos); } - -OFCondition IODSOPCommonModule::getTimezoneOffsetFromUTC(OFString& value, - const signed long pos) const +OFCondition IODSOPCommonModule::getTimezoneOffsetFromUTC(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_TimezoneOffsetFromUTC, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TimezoneOffsetFromUTC, *m_Item, value, pos); } - - -OFCondition IODSOPCommonModule::setSpecificCharacterSet(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setSpecificCharacterSet(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_SpecificCharacterSet, value); - } - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SpecificCharacterSet, value); + } + return result; } - -OFCondition IODSOPCommonModule::setSOPClassUID(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setSOPClassUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_SOPClassUID, value); - } - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SOPClassUID, value); + } + return result; } - -OFCondition IODSOPCommonModule::setSOPInstanceUID(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setSOPInstanceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUID, value); - } - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUID, value); + } + return result; } - -OFCondition IODSOPCommonModule::setInstanceCreationDate(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setInstanceCreationDate(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationDate, value); - } - return result; + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationDate, value); + } + return result; } - -OFCondition IODSOPCommonModule::setInstanceCreationTime(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setInstanceCreationTime(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationTime, value); - } - return result; + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationTime, value); + } + return result; } - -OFCondition IODSOPCommonModule::setInstanceCreatorUID(const OFString &value, - const OFBool checkValue) +OFCondition IODSOPCommonModule::setInstanceCreatorUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreatorUID, value); - } - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreatorUID, value); + } + return result; } - -OFCondition IODSOPCommonModule::setTimeZoneOffsetFromUTC(const OFString& value, - const OFBool checkValue) const +OFCondition IODSOPCommonModule::setTimeZoneOffsetFromUTC(const OFString& value, const OFBool checkValue) const { - OFCondition result; - if (checkValue) - { - result = DcmShortString::checkStringValue(value, "1"); + OFCondition result; + if (checkValue) + { + result = DcmShortString::checkStringValue(value, "1"); + if (result.good()) + { + if (value.length() != 5) + result = IOD_EC_InvalidElementValue; + } + } if (result.good()) { - if (value.length() != 5) result = IOD_EC_InvalidElementValue; + result = m_Item->putAndInsertOFStringArray(DCM_TimezoneOffsetFromUTC, value); } - } - if (result.good()) - { - result = m_Item->putAndInsertOFStringArray(DCM_TimezoneOffsetFromUTC, value); - } - return result; + return result; } diff --git a/dcmiod/libsrc/modsynchronization.cc b/dcmiod/libsrc/modsynchronization.cc index 4d496e3b..ee007916 100644 --- a/dcmiod/libsrc/modsynchronization.cc +++ b/dcmiod/libsrc/modsynchronization.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,230 +19,187 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/dcmiod/modsynchronisation.h" -#include "dcmtk/ofstd/ofstream.h" -#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrsh.h" -#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" - +#include "dcmtk/dcmiod/modsynchronisation.h" +#include "dcmtk/ofstd/ofstream.h" const OFString IODSynchronizationModule::m_ModuleName = "SynchronizationModule"; - -IODSynchronizationModule::IODSynchronizationModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODSynchronizationModule::IODSynchronizationModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODSynchronizationModule::IODSynchronizationModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODSynchronizationModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_SynchronizationFrameOfReferenceUID, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_SynchronizationTrigger, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_TriggerSourceOrType, "1","3", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_SynchronizationChannel, "2","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_AcquisitionTimeSynchronized, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_TimeSource, "1","3", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_TimeDistributionProtocol, "1","3", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_NTPSourceAddress, "1","3", getName(), DcmIODTypes::IE_FOR), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SynchronizationFrameOfReferenceUID, "1", "1", getName(), DcmIODTypes::IE_FOR), + OFTrue); + m_Rules->addRule(new IODRule(DCM_SynchronizationTrigger, "1", "1", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TriggerSourceOrType, "1", "3", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_SynchronizationChannel, "2", "1C", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionTimeSynchronized, "1", "1", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimeSource, "1", "3", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimeDistributionProtocol, "1", "3", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_NTPSourceAddress, "1", "3", getName(), DcmIODTypes::IE_FOR), OFTrue); } - - OFString IODSynchronizationModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODSynchronizationModule::~IODSynchronizationModule() { } - OFCondition IODSynchronizationModule::getSynchronizationFrameOfReferenceUID(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationFrameOfReferenceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationFrameOfReferenceUID, *m_Item, value, pos); } - - -OFCondition IODSynchronizationModule::getSynchronizationTrigger(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getSynchronizationTrigger(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationTrigger, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationTrigger, *m_Item, value, pos); } - -OFCondition IODSynchronizationModule::getTriggerSourceOrType(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getTriggerSourceOrType(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_TriggerSourceOrType, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TriggerSourceOrType, *m_Item, value, pos); } - OFCondition IODSynchronizationModule::getSynchronizationChannel(OFVector& value) const { - DcmElement *elem = NULL; - OFCondition result = m_Item->findAndGetElement(DCM_SynchronizationChannel, elem); - if (elem) - { - result = DcmIODUtil::getUint16ValuesFromElement(*elem, value); - } - return result; + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_SynchronizationChannel, elem); + if (elem) + { + result = DcmIODUtil::getUint16ValuesFromElement(*elem, value); + } + return result; } - -OFCondition IODSynchronizationModule::getAcquisitionTimeSynchronized(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getAcquisitionTimeSynchronized(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTimeSynchronized, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTimeSynchronized, *m_Item, value, pos); } - -OFCondition IODSynchronizationModule::getTimeSource(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getTimeSource(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_TimeSource, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TimeSource, *m_Item, value, pos); } - -OFCondition IODSynchronizationModule::getTimeDistributionProtocol(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getTimeDistributionProtocol(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_TimeDistributionProtocol, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TimeDistributionProtocol, *m_Item, value, pos); } - -OFCondition IODSynchronizationModule::getNTPSourceAddress(OFString& value, - const signed long pos) const +OFCondition IODSynchronizationModule::getNTPSourceAddress(OFString& value, const signed long pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_NTPSourceAddress, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_NTPSourceAddress, *m_Item, value, pos); } - -OFCondition IODSynchronizationModule::setSynchronizationFrameofReferenceUID(const OFString &value, +OFCondition IODSynchronizationModule::setSynchronizationFrameofReferenceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_SynchronizationFrameOfReferenceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SynchronizationFrameOfReferenceUID, value); + return result; } - -OFCondition IODSynchronizationModule::setSynchronizationTrigger(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setSynchronizationTrigger(const OFString& value, const OFBool checkValue) { - if (checkValue && !isValidSynchronizationTrigger(value)) - { - DCMIOD_ERROR("Synchronization Trigger does not allow value " << value << " (enumerated values)"); - return IOD_EC_InvalidElementValue; - } - return m_Item->putAndInsertOFStringArray(DCM_SynchronizationTrigger, value); + if (checkValue && !isValidSynchronizationTrigger(value)) + { + DCMIOD_ERROR("Synchronization Trigger does not allow value " << value << " (enumerated values)"); + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_SynchronizationTrigger, value); } - -OFCondition IODSynchronizationModule::setTriggerSourceOrType(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setTriggerSourceOrType(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_TriggerSourceOrType, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TriggerSourceOrType, value); + return result; } - -OFCondition IODSynchronizationModule::setSynchronizationChannel(const OFPair &value, +OFCondition IODSynchronizationModule::setSynchronizationChannel(const OFPair& value, const OFBool checkValue) { - (void)checkValue; - OFCondition result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.first, 0); - if (result.good()) - { - result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.second, 0); - } - return result; + (void)checkValue; + OFCondition result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.first, 0); + if (result.good()) + { + result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.second, 0); + } + return result; } - -OFCondition IODSynchronizationModule::setAcquisitionTimeSynchronized(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setAcquisitionTimeSynchronized(const OFString& value, const OFBool checkValue) { - if (checkValue && !isValidAcquisitionTimeSynchronized(value)) - { - DCMIOD_ERROR("Acquisition Time Synchronized must only allows values 'Y' and 'N' (enumerated values)"); - return IOD_EC_InvalidElementValue; - } - return m_Item->putAndInsertOFStringArray(DCM_AcquisitionTimeSynchronized, value); + if (checkValue && !isValidAcquisitionTimeSynchronized(value)) + { + DCMIOD_ERROR("Acquisition Time Synchronized must only allows values 'Y' and 'N' (enumerated values)"); + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_AcquisitionTimeSynchronized, value); } - -OFCondition IODSynchronizationModule::setTimeSource(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setTimeSource(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_TimeSource, value); - return result; + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TimeSource, value); + return result; } - -OFCondition IODSynchronizationModule::setTimeDistributionProtocol(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setTimeDistributionProtocol(const OFString& value, const OFBool checkValue) { - if (checkValue && !isValidTimeDistributionProtocol(value)) - { - DCMIOD_ERROR("Time Distribution Protocol does not allow value " << value << " (enumerated values)"); - return IOD_EC_InvalidElementValue; - } - return m_Item->putAndInsertOFStringArray(DCM_TimeDistributionProtocol, value); + if (checkValue && !isValidTimeDistributionProtocol(value)) + { + DCMIOD_ERROR("Time Distribution Protocol does not allow value " << value << " (enumerated values)"); + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_TimeDistributionProtocol, value); } - - -OFCondition IODSynchronizationModule::setNTPSourceAddress(const OFString &value, - const OFBool checkValue) +OFCondition IODSynchronizationModule::setNTPSourceAddress(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_NTPSourceAddress, value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_NTPSourceAddress, value); + return result; } - - OFBool IODSynchronizationModule::isValidAcquisitionTimeSynchronized(const OFString& value) { - return ( (value == "Y") || (value == "N") ); - + return ((value == "Y") || (value == "N")); } - OFBool IODSynchronizationModule::isValidTimeDistributionProtocol(const OFString& value) { - return ( (value == "NTP") || (value == "IRIG") || (value == "GPS") || (value == "SNTP") || (value == "PTP") ); + return ((value == "NTP") || (value == "IRIG") || (value == "GPS") || (value == "SNTP") || (value == "PTP")); } - OFBool IODSynchronizationModule::isValidSynchronizationTrigger(const OFString& value) { - return ( (value == "SOURCE") || (value == "EXTERNAL") || (value == "PASSTHRU") || (value == "NO TRIGGER") ); + return ((value == "SOURCE") || (value == "EXTERNAL") || (value == "PASSTHRU") || (value == "NO TRIGGER")); } - diff --git a/dcmiod/libsrc/modusfor.cc b/dcmiod/libsrc/modusfor.cc index 9058d5d6..3961ea5c 100644 --- a/dcmiod/libsrc/modusfor.cc +++ b/dcmiod/libsrc/modusfor.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,256 +19,218 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmiod/modusfor.h" -#include "dcmtk/ofstd/ofstream.h" -#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvrfd.h" -#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmiod/iodutil.h" - +#include "dcmtk/ofstd/ofstream.h" const OFString IODUSFoRModule::m_ModuleName = "UltrasoundFrameOfReferenceModule"; - -IODUSFoRModule::IODUSFoRModule(OFshared_ptr item, - OFshared_ptr rules) -: IODModule(item, rules) +IODUSFoRModule::IODUSFoRModule(OFshared_ptr item, OFshared_ptr rules) + : IODModule(item, rules) { - // reset element rules - resetRules(); + // reset element rules + resetRules(); } - IODUSFoRModule::IODUSFoRModule() -: IODModule() + : IODModule() { - resetRules(); + resetRules(); } - void IODUSFoRModule::resetRules() { - // parameters are tag, VM, type. Overwrite old rules if any. - m_Rules->addRule(new IODRule(DCM_VolumeFrameOfReferenceUID, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_UltrasoundAcquisitionGeometry, "1","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_ApexPosition, "3","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_VolumeToTransducerRelationship, "1","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_VolumeToTransducerMappingMatrix, "16","1", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_PatientFrameOfReferenceSource, "1","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_TableFrameOfReferenceUID, "1","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); - m_Rules->addRule(new IODRule(DCM_VolumeToTableMappingMatrix, "16","1C", getName(), DcmIODTypes::IE_FOR), OFTrue); + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_VolumeFrameOfReferenceUID, "1", "1", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_UltrasoundAcquisitionGeometry, "1", "1", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_ApexPosition, "3", "1C", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTransducerRelationship, "1", "1C", getName(), DcmIODTypes::IE_FOR), + OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTransducerMappingMatrix, "16", "1", getName(), DcmIODTypes::IE_FOR), + OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientFrameOfReferenceSource, "1", "1C", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TableFrameOfReferenceUID, "1", "1C", getName(), DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTableMappingMatrix, "16", "1C", getName(), DcmIODTypes::IE_FOR), OFTrue); } - OFString IODUSFoRModule::getName() const { - return m_ModuleName; + return m_ModuleName; } - IODUSFoRModule::~IODUSFoRModule() { - // Nothing to do + // Nothing to do } - -OFCondition IODUSFoRModule::getVolumeFrameOfReferenceUID(OFString& value, - const long signed int pos) const +OFCondition IODUSFoRModule::getVolumeFrameOfReferenceUID(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_VolumeFrameOfReferenceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_VolumeFrameOfReferenceUID, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getUltrasoundAcquisitionGeometry(OFString& value, - const long signed int pos) const +OFCondition IODUSFoRModule::getUltrasoundAcquisitionGeometry(OFString& value, const long signed int pos) const { - return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); } - OFCondition IODUSFoRModule::getApexPosition(OFVector& value) { - return DcmIODUtil::getFloat64ValuesFromItem(DCM_ApexPosition, *m_Item, value); + return DcmIODUtil::getFloat64ValuesFromItem(DCM_ApexPosition, *m_Item, value); } - -OFCondition IODUSFoRModule::getApexPosition(Float64& value, - const long unsigned int pos) const +OFCondition IODUSFoRModule::getApexPosition(Float64& value, const unsigned long pos) const { - return DcmIODUtil::getFloat64ValueFromItem(DCM_ApexPosition, *m_Item, value, pos); + return DcmIODUtil::getFloat64ValueFromItem(DCM_ApexPosition, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getVolumetoTransducerRelationship(OFString& value, - const long signed int pos) +OFCondition IODUSFoRModule::getVolumetoTransducerRelationship(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(Float64& value, - const signed long pos) const +OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(Float64& value, const unsigned long pos) const { - return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value, pos); + return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(OFVector< Float64 >& value) +OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(OFVector& value) { - return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value); + return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value); } - -OFCondition IODUSFoRModule::getPatientFrameofReferenceSource(OFString& value, - const long signed int pos) +OFCondition IODUSFoRModule::getPatientFrameofReferenceSource(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromItem(DCM_PatientFrameOfReferenceSource, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_PatientFrameOfReferenceSource, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getTableFrameofReferenceUID(OFString& value, - const long signed int pos) +OFCondition IODUSFoRModule::getTableFrameofReferenceUID(OFString& value, const long signed int pos) { - return DcmIODUtil::getStringValueFromItem(DCM_TableFrameOfReferenceUID, *m_Item, value, pos); + return DcmIODUtil::getStringValueFromItem(DCM_TableFrameOfReferenceUID, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(Float64& value, - const long signed int pos) const +OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(Float64& value, const unsigned long pos) const { - return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value, pos); + return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value, pos); } - -OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(OFVector< Float64 >& value) +OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(OFVector& value) { - return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value); + return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value); } - -OFCondition IODUSFoRModule::setVolumeFrameOfReferenceUID(const OFString& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setVolumeFrameOfReferenceUID(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_VolumeFrameOfReferenceUID, value); - return result; + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_VolumeFrameOfReferenceUID, value); + return result; } - -OFCondition IODUSFoRModule::setUltrasoundAcquisitionGeometry(const OFString& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setUltrasoundAcquisitionGeometry(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_UltrasoundAcquisitionGeometry, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_UltrasoundAcquisitionGeometry, value); + return result; } - -OFCondition IODUSFoRModule::setApexPosition(const Float64& xValue, - const Float64& yValue, - const Float64& zValue, - const OFBool) +OFCondition +IODUSFoRModule::setApexPosition(const Float64& xValue, const Float64& yValue, const Float64& zValue, const OFBool) { - DcmElement *elem = DcmItem::newDicomElement(DCM_ApexPosition); - + DcmElement* elem = DcmItem::newDicomElement(DCM_ApexPosition); - OFCondition result = elem->putFloat64(xValue, 0); - if (result.good()) result = elem->putFloat64(yValue, 1); - if (result.good()) result = elem->putFloat64(zValue, 2); - m_Item->insert(elem); + OFCondition result = elem->putFloat64(xValue, 0); + if (result.good()) + result = elem->putFloat64(yValue, 1); + if (result.good()) + result = elem->putFloat64(zValue, 2); + m_Item->insert(elem); - return result; + return result; } - -OFCondition IODUSFoRModule::setVolumetoTransducerRelationship(const OFString& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setVolumetoTransducerRelationship(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_VolumeToTransducerRelationship, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_VolumeToTransducerRelationship, value); + return result; } - -OFCondition IODUSFoRModule::setVolumetoTransducerMappingMatrix(const OFVector< Float64 >& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setVolumetoTransducerMappingMatrix(const OFVector& value, const OFBool checkValue) { - size_t vm = value.size(); - if ( checkValue && (vm != 16) ) - { - return EC_ValueMultiplicityViolated; - } - - OFCondition result; - - DcmElement* elem = NULL; - result = DcmItem::newDicomElement(elem, DCM_VolumeToTransducerMappingMatrix); - if (result.good()) - { - for (size_t n = 0; result.good() && n < vm; n++) + size_t vm = value.size(); + if (checkValue && (vm != 16)) { - result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + return EC_ValueMultiplicityViolated; } - } - if (result.good()) - { - result = m_Item->insert(elem); - if (result.bad()) delete elem; - } - return result; -} + OFCondition result; -OFCondition IODUSFoRModule::setPatientFrameOfReferenceSource(const OFString& value, - const OFBool checkValue) -{ - OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_PatientFrameOfReferenceSource, value); - return result; + DcmElement* elem = NULL; + result = DcmItem::newDicomElement(elem, DCM_VolumeToTransducerMappingMatrix); + if (result.good()) + { + for (size_t n = 0; result.good() && n < vm; n++) + { + result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + } + } + if (result.good()) + { + result = m_Item->insert(elem); + if (result.bad()) + delete elem; + } + return result; } - -OFCondition IODUSFoRModule::setTableFrameofReferenceUID(const OFString& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setPatientFrameOfReferenceSource(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_Item->putAndInsertOFStringArray(DCM_TableFrameOfReferenceUID, value); - return result; + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientFrameOfReferenceSource, value); + return result; } +OFCondition IODUSFoRModule::setTableFrameofReferenceUID(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TableFrameOfReferenceUID, value); + return result; +} -OFCondition IODUSFoRModule::setVolumeToTableMappingMatrix(const OFVector< Float64 >& value, - const OFBool checkValue) +OFCondition IODUSFoRModule::setVolumeToTableMappingMatrix(const OFVector& value, const OFBool checkValue) { - size_t vm = value.size(); - if ( checkValue && (vm != 16) ) - { - return EC_ValueMultiplicityViolated; - } - - OFCondition result; - - DcmElement* elem = NULL; - result = DcmItem::newDicomElement(elem, DCM_VolumeToTableMappingMatrix); - if (result.good()) - { - for (size_t n = 0; result.good() && (n < vm); n++) + size_t vm = value.size(); + if (checkValue && (vm != 16)) + { + return EC_ValueMultiplicityViolated; + } + + OFCondition result; + + DcmElement* elem = NULL; + result = DcmItem::newDicomElement(elem, DCM_VolumeToTableMappingMatrix); + if (result.good()) + { + for (size_t n = 0; result.good() && (n < vm); n++) + { + result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + } + } + if (result.good()) { - result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); + result = m_Item->insert(elem); + if (result.bad()) + delete elem; } - } - if (result.good()) - { - result = m_Item->insert(elem); - if (result.bad()) delete elem; - } - return result; + return result; } diff --git a/dcmiod/tests/CMakeLists.txt b/dcmiod/tests/CMakeLists.txt index 1ebae734..b81014fa 100644 --- a/dcmiod/tests/CMakeLists.txt +++ b/dcmiod/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # declare executables -DCMTK_ADD_EXECUTABLE(dcmiod_tests tests tcielabutil timagepixel) +DCMTK_ADD_EXECUTABLE(dcmiod_tests tests tcielabutil tcodes timagepixel) # make sure executables are linked to the corresponding libraries DCMTK_TARGET_LINK_MODULES(dcmiod_tests dcmiod dcmdata oflog ofstd) diff --git a/dcmiod/tests/Makefile.dep b/dcmiod/tests/Makefile.dep index e1438836..bcde2259 100644 --- a/dcmiod/tests/Makefile.dep +++ b/dcmiod/tests/Makefile.dep @@ -1,13 +1,15 @@ tcielabutil.o: tcielabutil.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../../ofstd/include/dcmtk/ofstd/oftest.h \ - ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/ioddef.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofrand.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ @@ -47,9 +49,130 @@ tcielabutil.o: tcielabutil.cc \ ../../oflog/include/dcmtk/oflog/spi/logfact.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h +tcodes.o: tcodes.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../ofstd/include/dcmtk/ofstd/ofrand.h \ - ../include/dcmtk/dcmiod/cielabutil.h ../include/dcmtk/dcmiod/ioddef.h + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ @@ -101,30 +224,18 @@ tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/tracelog.h timagepixel.o: timagepixel.cc \ ../../config/include/dcmtk/config/osconfig.h \ - ../../ofstd/include/dcmtk/ofstd/oftest.h \ - ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../include/dcmtk/dcmiod/iodimage.h ../include/dcmtk/dcmiod/iodcommn.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ - ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../ofstd/include/dcmtk/ofstd/ofexit.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -138,6 +249,7 @@ timagepixel.o: timagepixel.cc \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -149,22 +261,10 @@ timagepixel.o: timagepixel.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmiod/iodimage.h \ - ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ - ../../ofstd/include/dcmtk/ofstd/diag/push.def \ - ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ - ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ - ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ - ../include/dcmtk/dcmiod/iodcommn.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ - ../include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmiod/modcommoninstanceref.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ @@ -172,8 +272,15 @@ timagepixel.o: timagepixel.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ @@ -234,18 +341,32 @@ timagepixel.o: timagepixel.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodmacro.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodreferences.h \ + ../include/dcmtk/dcmiod/modequipment.h ../include/dcmtk/dcmiod/modfor.h \ + ../include/dcmtk/dcmiod/modgeneralseries.h \ + ../include/dcmtk/dcmiod/modgeneralstudy.h \ + ../include/dcmtk/dcmiod/modpatient.h \ ../include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../include/dcmtk/dcmiod/modgeneralstudy.h \ - ../include/dcmtk/dcmiod/iodmacro.h \ - ../include/dcmtk/dcmiod/modequipment.h \ - ../include/dcmtk/dcmiod/modgeneralseries.h \ - ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modsopcommon.h \ - ../include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../include/dcmtk/dcmiod/iodreferences.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/modsopcommon.h \ ../include/dcmtk/dcmiod/modgeneralimage.h \ ../include/dcmtk/dcmiod/modimagepixelvariant.h \ ../include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../include/dcmtk/dcmiod/modfloatingpointimagepixel.h \ ../include/dcmtk/dcmiod/modimagepixel.h \ - ../include/dcmtk/dcmiod/modfloatingpointimagepixel.h + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h diff --git a/dcmiod/tests/Makefile.in b/dcmiod/tests/Makefile.in index 4b8699bb..05d44501 100644 --- a/dcmiod/tests/Makefile.in +++ b/dcmiod/tests/Makefile.in @@ -24,7 +24,7 @@ LIBDIRS = -L$(top_srcdir)/libsrc -L$(dcmioddir)/libsrc -L$(dcmdatadir)/libsrc \ LOCALLIBS = -ldcmiod -ldcmdata -loflog -lofstd \ $(TIFFLIBS) $(PNGLIBS) $(ZLIBLIBS) $(CHARCONVLIBS) $(MATHLIBS) -test_objs = tests.o tcielabutil.o timagepixel.o +test_objs = tests.o tcielabutil.o tcodes.o timagepixel.o objs = tests.o $(test_objs) progs = tests @@ -38,10 +38,10 @@ install: all check: tests - ./tests + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests check-exhaustive: tests - ./tests -x + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests -x clean: diff --git a/dcmiod/tests/tcielabutil.cc b/dcmiod/tests/tcielabutil.cc index 8cbab8c7..c2933b3c 100644 --- a/dcmiod/tests/tcielabutil.cc +++ b/dcmiod/tests/tcielabutil.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2017-2018, OFFIS e.V. + * Copyright (C) 2017-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -19,110 +19,107 @@ * */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ - -#include "dcmtk/ofstd/oftest.h" -#include "dcmtk/ofstd/ofrand.h" #include "dcmtk/dcmiod/cielabutil.h" - +#include "dcmtk/ofstd/ofrand.h" +#include "dcmtk/ofstd/oftest.h" OFTEST(dcmiod_tcielabutil) { - // Result variables for testing - double r1, r2, r3; - r1=r2=r3 = 0.0; - - // Test RGB -> CIELab conversion with medium values - IODCIELabUtil::rgb2Lab(r1, r2, r3 /* L,a,b */, 0.5, 0.5, 0.5); - OFCHECK( fabs(53.388 - r1) < 0.001 ); - OFCHECK( fabs(0.006 - r2) < 0.001 ); - OFCHECK( fabs(-0.010 - r3) < 0.001 ); - - // Test RGB -> CIEXYZ conversion with medium values - r1=r2=r3 = 0; - IODCIELabUtil::rgb2Xyz(r1, r2, r3 /* X,Y,Z */, 0.5, 0.5, 0.5); - OFCHECK( fabs(0.203 - r1) < 0.001 ); - OFCHECK( fabs(0.214 - r2) < 0.001 ); - OFCHECK( fabs(0.233 - r3) < 0.001 ); - - // Test RGB -> CIELab conversion with minimum value - r1=r2=r3 = 0; - IODCIELabUtil::rgb2Lab(r1, r2, r3 /* L,a,b */, 0, 0, 0); - OFCHECK( fabs(0 - r1) < 0.001 ); - OFCHECK( fabs(0 - r2) < 0.001 ); - OFCHECK( fabs(0 - r3) < 0.001 ); - - // Test RGB -> XYZ conversion with minimum values - r1=r2=r3 = 0; - IODCIELabUtil::rgb2Xyz(r1, r2, r3 /* X,Y,Z */, 0, 0, 0); - OFCHECK( fabs(0 - r1) < 0.001 ); - OFCHECK( fabs(0 - r2) < 0.001 ); - OFCHECK( fabs(0 - r3) < 0.001 ); - - // Test DICOM CIELab to "normalized" CIELab conversion with maximum values - r1=r2=r3 = 0; - IODCIELabUtil::dicomlab2Lab(r1, r2, r3, 65535, 65535, 65535 ); - OFCHECK( fabs(100 - r1) < 0.001 ); - OFCHECK( fabs(127 - r2) < 0.001 ); - OFCHECK( fabs(127 - r3) < 0.001 ); - - // Test DICOM CIELab to "normalized" CIELab conversion with minimum values - r1=r2=r3 = 0; - IODCIELabUtil::dicomlab2Lab(r1, r2, r3, 0, 0, 0 ); - OFCHECK( fabs(0 - r1) < 0.001 ); - OFCHECK( fabs(-128 - r2) < 0.001 ); - OFCHECK( fabs(-128 - r3) < 0.001 ); - - // Convert between colorspaces back and forth and check whether deviation after - // roundtrip is less than around 1 promille - - // Initialize random numbers - OFRandom rnd; - - // We do 1000 runs - for (size_t numRun = 0; numRun< 1000; numRun++) - { - // i1, i2, i3: Input for conversion - // r1, r2, r3: Results of conversion - // o1, o2, o3: Output of inverse conversion (should equal i1, i2, i3) - double i1, i2, i3, o1, o2, o3; - i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; - - // Roundtrip RGB -> CIELab -> RGB - i1 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - i2 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - i3 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - IODCIELabUtil::rgb2Lab(r1, r2, r3, i1, i2, i3); - IODCIELabUtil::lab2Rgb(o1, o2, o3, r1, r2, r3); - OFCHECK( fabs(i1 - o1) < 0.001 ); - OFCHECK( fabs(i2 - o2) < 0.001 ); - OFCHECK( fabs(i3 - o3) < 0.001 ); - - // Roundtrip CIELab -> DICOM CIELab -> CIELab - i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; - i1 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1) * 100.0; - i2 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1) * 255.0 - 128; - i3 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1) * 255.0 - 128; - IODCIELabUtil::lab2DicomLab(r1, r2, r3, i1, i2, i3); - IODCIELabUtil::dicomlab2Lab(o1, o2, o3, r1, r2, r3); - OFCHECK( fabs(i1 - o1) < 0.001 ); - OFCHECK( fabs(i2 - o2) < 0.001 ); - OFCHECK( fabs(i3 - o3) < 0.001 ); - - // Roundtrip RGB -> CIEXYZ -> CIELab -> dicomCIELab -> RGB - i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; - i1 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - i2 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - i3 = OFstatic_cast(double,rnd.getRND32()) / OFstatic_cast(Uint32,-1); - IODCIELabUtil::rgb2Xyz(r1, r2, r3, i1, i2, i3); - IODCIELabUtil::xyz2Lab(o1, o2, o3, r1, r2, r3); - IODCIELabUtil::lab2DicomLab(r1, r2, r3, o1, o2, o3); - IODCIELabUtil::dicomLab2RGB(o1, o2, o3, r1, r2, r3); - - OFCHECK( fabs(i1 - o1) < 0.001 ); - OFCHECK( fabs(i2 - o2) < 0.001 ); - OFCHECK( fabs(i3 - o3) < 0.001 ); - - } + // Result variables for testing + double r1, r2, r3; + r1 = r2 = r3 = 0.0; + + // Test RGB -> CIELab conversion with medium values + IODCIELabUtil::rgb2Lab(r1, r2, r3 /* L,a,b */, 0.5, 0.5, 0.5); + OFCHECK(fabs(53.388 - r1) < 0.001); + OFCHECK(fabs(0.006 - r2) < 0.001); + OFCHECK(fabs(-0.010 - r3) < 0.001); + + // Test RGB -> CIEXYZ conversion with medium values + r1 = r2 = r3 = 0; + IODCIELabUtil::rgb2Xyz(r1, r2, r3 /* X,Y,Z */, 0.5, 0.5, 0.5); + OFCHECK(fabs(0.203 - r1) < 0.001); + OFCHECK(fabs(0.214 - r2) < 0.001); + OFCHECK(fabs(0.233 - r3) < 0.001); + + // Test RGB -> CIELab conversion with minimum value + r1 = r2 = r3 = 0; + IODCIELabUtil::rgb2Lab(r1, r2, r3 /* L,a,b */, 0, 0, 0); + OFCHECK(fabs(0 - r1) < 0.001); + OFCHECK(fabs(0 - r2) < 0.001); + OFCHECK(fabs(0 - r3) < 0.001); + + // Test RGB -> XYZ conversion with minimum values + r1 = r2 = r3 = 0; + IODCIELabUtil::rgb2Xyz(r1, r2, r3 /* X,Y,Z */, 0, 0, 0); + OFCHECK(fabs(0 - r1) < 0.001); + OFCHECK(fabs(0 - r2) < 0.001); + OFCHECK(fabs(0 - r3) < 0.001); + + // Test DICOM CIELab to "normalized" CIELab conversion with maximum values + r1 = r2 = r3 = 0; + IODCIELabUtil::dicomlab2Lab(r1, r2, r3, 65535, 65535, 65535); + OFCHECK(fabs(100 - r1) < 0.001); + OFCHECK(fabs(127 - r2) < 0.001); + OFCHECK(fabs(127 - r3) < 0.001); + + // Test DICOM CIELab to "normalized" CIELab conversion with minimum values + r1 = r2 = r3 = 0; + IODCIELabUtil::dicomlab2Lab(r1, r2, r3, 0, 0, 0); + OFCHECK(fabs(0 - r1) < 0.001); + OFCHECK(fabs(-128 - r2) < 0.001); + OFCHECK(fabs(-128 - r3) < 0.001); + + // Convert between colorspaces back and forth and check whether deviation after + // roundtrip is less than around 1 promille + + // Initialize random numbers + OFRandom rnd; + + // We do 1000 runs + for (size_t numRun = 0; numRun < 1000; numRun++) + { + // i1, i2, i3: Input for conversion + // r1, r2, r3: Results of conversion + // o1, o2, o3: Output of inverse conversion (should equal i1, i2, i3) + double i1, i2, i3, o1, o2, o3; + i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; + + // Roundtrip RGB -> CIELab -> RGB + i1 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + i2 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + i3 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + IODCIELabUtil::rgb2Lab(r1, r2, r3, i1, i2, i3); + IODCIELabUtil::lab2Rgb(o1, o2, o3, r1, r2, r3); + OFCHECK(fabs(i1 - o1) < 0.001); + OFCHECK(fabs(i2 - o2) < 0.001); + OFCHECK(fabs(i3 - o3) < 0.001); + + // Roundtrip CIELab -> DICOM CIELab -> CIELab + i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; + i1 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1) * 100.0; + i2 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1) * 255.0 - 128; + i3 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1) * 255.0 - 128; + IODCIELabUtil::lab2DicomLab(r1, r2, r3, i1, i2, i3); + IODCIELabUtil::dicomlab2Lab(o1, o2, o3, r1, r2, r3); + OFCHECK(fabs(i1 - o1) < 0.001); + OFCHECK(fabs(i2 - o2) < 0.001); + OFCHECK(fabs(i3 - o3) < 0.001); + + // Roundtrip RGB -> CIEXYZ -> CIELab -> dicomCIELab -> RGB + i1 = i2 = i3 = r1 = r2 = r3 = o1 = o2 = o3 = 0.0; + i1 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + i2 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + i3 = OFstatic_cast(double, rnd.getRND32()) / OFstatic_cast(Uint32, -1); + IODCIELabUtil::rgb2Xyz(r1, r2, r3, i1, i2, i3); + IODCIELabUtil::xyz2Lab(o1, o2, o3, r1, r2, r3); + IODCIELabUtil::lab2DicomLab(r1, r2, r3, o1, o2, o3); + IODCIELabUtil::dicomLab2RGB(o1, o2, o3, r1, r2, r3); + + OFCHECK(fabs(i1 - o1) < 0.001); + OFCHECK(fabs(i2 - o2) < 0.001); + OFCHECK(fabs(i3 - o3) < 0.001); + } } diff --git a/dcmiod/tests/tcodes.cc b/dcmiod/tests/tcodes.cc new file mode 100644 index 00000000..dd959a84 --- /dev/null +++ b/dcmiod/tests/tcodes.cc @@ -0,0 +1,164 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmect + * + * Author: Michael Onken + * + * Purpose: Tests for dcmiod's Code Sequence Macro implementation + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/ofstd/oftest.h" + +static OFLogger tCodeLogger = OFLog::getLogger("dcmtk.test.t_codes"); + +static void clearCode(CodeSequenceMacro& c); + +OFTEST(dcmiod_codes) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + // Most basic, classic "Code Value" variant + CodeSequenceMacro c("Value", "99DCMTK", "Classic code", "Version 1"); + OFCHECK(c.check().good()); + OFString val; + OFCHECK(c.getCodeValue(val, -1, OFTrue /* autoTag */).good()); + OFCHECK(val == "Value"); + OFCHECK(c.getCodeValue(val, -1, OFFalse /* autoTag off */).good()); + OFCHECK(val == "Value"); + OFCHECK(c.getCodingSchemeDesignator(val).good()); + OFCHECK(val == "99DCMTK"); + OFCHECK(c.getCodeMeaning(val).good()); + OFCHECK(val == "Classic code"); + OFCHECK(c.getCodingSchemeVersion(val).good()); + OFCHECK(val == "Version 1"); + OFCHECK(c.getLongCodeValue(val).bad()); + OFCHECK(c.getURNCodeValue(val).bad()); + OFCHECK(c.check().good()); + + clearCode(c); + val.clear(); + + // "URN Code Value" variant + OFCHECK(c.set("http://www.open-connections.de", "99DCMTK", "URN code", "Version 1", OFTrue, OFTrue /* autoTag */) + .good()); + OFCHECK(c.check().good()); + OFCHECK(c.getCodeValue(val, -1, OFTrue /* autoTag */).good()); + OFCHECK(val == "http://www.open-connections.de"); + val.clear(); + OFCHECK(c.getCodeValue(val, -1, OFFalse /* autoTag off */).bad()); + OFCHECK(val.empty()); + OFCHECK(c.getCodingSchemeDesignator(val).good()); + OFCHECK(val == "99DCMTK"); + OFCHECK(c.getCodeMeaning(val).good()); + OFCHECK(val == "URN code"); + OFCHECK(c.getCodingSchemeVersion(val).good()); + OFCHECK(val == "Version 1"); + OFCHECK(c.getLongCodeValue(val).bad()); + OFCHECK(c.getURNCodeValue(val).good()); + OFCHECK(val == "http://www.open-connections.de"); + OFCHECK(c.check().good()); + + clearCode(c); + val.clear(); + + // "Long Code Value" variant + OFCHECK(c.set("Open Connections GmbH", "99DCMTK", "Long code", "Version 1", OFTrue, OFTrue /* autoTag */).good()); + OFCHECK(c.check().good()); + OFCHECK(c.getCodeValue(val, -1, OFTrue /* autoTag */).good()); + OFCHECK(val == "Open Connections GmbH"); + val.clear(); + OFCHECK(c.getCodeValue(val, -1, OFFalse /* autoTag off */).bad()); + OFCHECK(val.empty()); + OFCHECK(c.getCodingSchemeDesignator(val).good()); + OFCHECK(val == "99DCMTK"); + OFCHECK(c.getCodeMeaning(val).good()); + OFCHECK(val == "Long code"); + OFCHECK(c.getCodingSchemeVersion(val).good()); + OFCHECK(val == "Version 1"); + OFCHECK(c.getURNCodeValue(val).bad()); + OFCHECK(c.getLongCodeValue(val).good()); + OFCHECK(val == "Open Connections GmbH"); + OFCHECK(c.check().good()); + + clearCode(c); + val.clear(); + + // Check only single code value is set internally (old values are deleted) + OFCHECK(c.set("http://www.open-connections.de", "99DCMTK", "URN code", "Version 1", OFTrue, OFTrue /* autoTag */) + .good()); + OFCHECK(c.set("Value", "99DCMTK", "Classic code", "Version 1").good()); + OFCHECK(c.getLongCodeValue(val).bad()); + OFCHECK(c.getURNCodeValue(val).bad()); + + clearCode(c); + val.clear(); + + OFCHECK(c.set("http://www.open-connections.de", "99DCMTK", "URN code", "Version 1", OFTrue, OFTrue /* autoTag */) + .good()); + OFCHECK(c.set("Open Connections GmbH", "99DCMTK", "Long code", "Version 1", OFTrue, OFTrue /* autoTag */).good()); + OFCHECK(c.getURNCodeValue(val).bad()); + OFCHECK(c.getCodeValue(val, -1, OFFalse /*autoTag off */).bad()); + + clearCode(c); + val.clear(); + + // Failure: URN Code Value without autoTag + OFCHECK(c.set("http://www.open-connections.de/this/url/is/over/64/characters/long", + "99DCMTK", + "URN code", + "Version 1", + OFTrue, + OFFalse /* autoTag off */) + .bad()); + OFCHECK(c.check().bad()); + + clearCode(c); + val.clear(); + + // Failure: Long Code Value without autoTag + OFCHECK(c.set("Open Connections GmbH, Oldenburg, Germany, c/o Name over 64 characters long", + "99DCMTK", + "URN code", + "Version 1", + OFTrue, + OFFalse /* autoTag off */) + .bad()); + OFCHECK(c.check().bad()); +} + +static void clearCode(CodeSequenceMacro& c) +{ + c.clearData(); + OFString val; + c.getCodeValue(val); + OFCHECK(val.empty()); + c.getURNCodeValue(val); + OFCHECK(val.empty()); + c.getLongCodeValue(val); + OFCHECK(val.empty()); + c.getCodingSchemeDesignator(val); + OFCHECK(val.empty()); + c.getCodeMeaning(val); + OFCHECK(val.empty()); + c.getCodingSchemeVersion(val); + OFCHECK(val.empty()); +} diff --git a/dcmiod/tests/tests.cc b/dcmiod/tests/tests.cc index c1528a9c..f450a82a 100644 --- a/dcmiod/tests/tests.cc +++ b/dcmiod/tests/tests.cc @@ -22,6 +22,7 @@ #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/oftest.h" +OFTEST_REGISTER(dcmiod_codes); OFTEST_REGISTER(dcmiod_tcielabutil); OFTEST_REGISTER(dcmiod_imagepixel); OFTEST_MAIN("dcmiod") diff --git a/dcmiod/tests/timagepixel.cc b/dcmiod/tests/timagepixel.cc index 2c4ed75f..9b997ccf 100644 --- a/dcmiod/tests/timagepixel.cc +++ b/dcmiod/tests/timagepixel.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, OFFIS e.V. + * Copyright (C) 2016-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -15,20 +15,20 @@ * * Author: Jan Schlamelcher * - * Purpose: Tests for dcmiod's color conversion functionalities + * Purpose: Tests for Image Pixel Module functionalities * */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ - -#include "dcmtk/ofstd/oftest.h" #include "dcmtk/dcmiod/iodimage.h" -#include "dcmtk/dcmiod/modimagepixel.h" #include "dcmtk/dcmiod/modfloatingpointimagepixel.h" +#include "dcmtk/dcmiod/modimagepixel.h" +#include "dcmtk/ofstd/oftest.h" OFTEST(dcmiod_imagepixel) { - DcmIODImage,IODFloatingPointImagePixelModule> image1; - DcmIODImage,IODImagePixelModule,IODDoubleFloatingPointImagePixelModule> image2( OFin_place > ); + DcmIODImage, IODFloatingPointImagePixelModule> image1; + DcmIODImage, IODImagePixelModule, IODDoubleFloatingPointImagePixelModule> image2( + OFin_place >); } diff --git a/dcmjpeg/apps/dcmdjpeg.cc b/dcmjpeg/apps/dcmdjpeg.cc index b43ee65a..1ed23296 100644 --- a/dcmjpeg/apps/dcmdjpeg.cc +++ b/dcmjpeg/apps/dcmdjpeg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2019, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) const char *opt_ofname = NULL; E_FileReadMode opt_readMode = ERM_autoDetect; - E_FileWriteMode opt_writeMode = EWM_fileformat; + E_FileWriteMode opt_writeMode = EWM_createNewMeta; E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; E_EncodingType opt_oenctype = EET_ExplicitLength; @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) cmd.endOptionBlock(); cmd.beginOptionBlock(); - if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-file")) opt_writeMode = EWM_createNewMeta; if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; cmd.endOptionBlock(); @@ -326,10 +326,6 @@ int main(int argc, char *argv[]) OFLOG_INFO(dcmdjpegLogger, "creating output file " << opt_ofname); - // update file meta information with new SOP Instance UID - if ((opt_uidcreation == EUC_always) && (opt_writeMode == EWM_fileformat)) - opt_writeMode = EWM_updateMeta; - fileformat.loadAllDataIntoMemory(); error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); diff --git a/dcmjpeg/docs/dcmj2pnm.man b/dcmjpeg/docs/dcmj2pnm.man index 7804b8bc..2b982b8d 100644 --- a/dcmjpeg/docs/dcmj2pnm.man +++ b/dcmjpeg/docs/dcmj2pnm.man @@ -127,7 +127,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -397,7 +397,7 @@ JPEG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -574,6 +574,6 @@ It is an error if no data dictionary can be loaded. \section dcmj2pnm_copyright COPYRIGHT -Copyright (C) 2001-2018 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2001-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmjpeg/docs/dcmjpeg.dox b/dcmjpeg/docs/dcmjpeg.dox index 147d3d09..4f59d07c 100644 --- a/dcmjpeg/docs/dcmjpeg.dox +++ b/dcmjpeg/docs/dcmjpeg.dox @@ -39,11 +39,6 @@ if (fileformat.loadFile("test.dcm").good()) if (dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms).good() && dataset->canWriteXfer(EXS_JPEGProcess14SV1)) { - // force the meta-header UIDs to be re-generated when storing the file - // since the UIDs in the data set may have changed - delete metaInfo->remove(DCM_MediaStorageSOPClassUID); - delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID); - // store in lossless JPEG format fileformat.saveFile("test_jpeg.dcm", EXS_JPEGProcess14SV1); } diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h b/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h index 4a747ce9..7c31575d 100644 --- a/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2017, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -61,6 +61,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -68,7 +72,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -118,6 +123,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -126,7 +135,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -140,6 +150,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -149,7 +163,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h b/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h index 9fda0226..b521bab1 100644 --- a/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2014, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -65,6 +65,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -72,7 +76,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -122,6 +127,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -130,7 +139,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -144,6 +154,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -153,7 +167,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmjpeg/libsrc/djcodecd.cc b/dcmjpeg/libsrc/djcodecd.cc index f7280d97..c13d4673 100644 --- a/dcmjpeg/libsrc/djcodecd.cc +++ b/dcmjpeg/libsrc/djcodecd.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2018, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -65,9 +65,16 @@ OFCondition DJCodecDecoder::decode( DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const + const DcmStack& objStack, + OFBool& removeOldRep) const { OFCondition result = EC_Normal; + + // this codec may modify the DICOM header such that the previous pixel + // representation is not valid anymore. Indicate this to the caller + // to trigger removal. + removeOldRep = OFTrue; + // assume we can cast the codec parameter to what we need const DJCodecParameter *djcp = OFreinterpret_cast(const DJCodecParameter*, cp); @@ -594,7 +601,8 @@ OFCondition DJCodecDecoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* pixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we are a decoder only return EC_IllegalCall; @@ -608,7 +616,8 @@ OFCondition DJCodecDecoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we don't support re-coding for now return EC_IllegalCall; diff --git a/dcmjpeg/libsrc/djcodece.cc b/dcmjpeg/libsrc/djcodece.cc index f61d9531..b052e0d5 100644 --- a/dcmjpeg/libsrc/djcodece.cc +++ b/dcmjpeg/libsrc/djcodece.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2019, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -81,7 +81,8 @@ OFCondition DJCodecEncoder::decode( DcmPixelSequence * /* pixSeq */, DcmPolymorphOBOW& /* uncompressedPixelData */, const DcmCodecParameter * /* cp */, - const DcmStack& /* objStack */) const + const DcmStack& /* objStack */, + OFBool& /* removeOldRep */ ) const { // we are an encoder only return EC_IllegalCall; @@ -111,7 +112,8 @@ OFCondition DJCodecEncoder::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we don't support re-coding for now return EC_IllegalCall; @@ -124,9 +126,16 @@ OFCondition DJCodecEncoder::encode( const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const + DcmStack & objStack, + OFBool& removeOldRep) const { OFCondition result = EC_Normal; + + // this codec may modify the DICOM header such that the previous pixel + // representation is not valid anymore. Indicate this to the caller + // to trigger removal. + removeOldRep = OFTrue; + // assume we can cast the codec parameter to what we need const DJCodecParameter *djcp = OFreinterpret_cast(const DJCodecParameter*, cp); @@ -823,10 +832,9 @@ OFCondition DJCodecEncoder::updateDerivationDescription( // assume we can cast the codec parameter to what we need DJCodecParameter *djcp = OFconst_cast(DJCodecParameter*, cp); - if (djcp->getTrueLosslessMode()) - result = DcmCodec::insertCodeSequence(dataset, DCM_DerivationCodeSequence, "DCM", "121327", "Full fidelity image"); - else // pseudo-lossless mode may also result in lossy compression + if (!isLosslessProcess() || !djcp->getTrueLosslessMode()) result = DcmCodec::insertCodeSequence(dataset, DCM_DerivationCodeSequence, "DCM", "113040", "Lossy Compression"); + } return result; } diff --git a/dcmjpls/apps/CMakeLists.txt b/dcmjpls/apps/CMakeLists.txt index 2a9a4526..0cb3f53e 100644 --- a/dcmjpls/apps/CMakeLists.txt +++ b/dcmjpls/apps/CMakeLists.txt @@ -8,5 +8,5 @@ endforeach() # make sure executables are linked to the corresponding libraries foreach(PROGRAM dcmcjpls dcmdjpls dcml2pnm) - DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpls charls dcmimage dcmimgle dcmdata oflog ofstd ofstd) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpls dcmtkcharls dcmimage dcmimgle dcmdata oflog ofstd ofstd) endforeach() diff --git a/dcmjpls/apps/Makefile.in b/dcmjpls/apps/Makefile.in index 33ef2597..58608a19 100644 --- a/dcmjpls/apps/Makefile.in +++ b/dcmjpls/apps/Makefile.in @@ -44,7 +44,7 @@ dcmjplslib = -ldcmjpls libcharlsdir = $(dcmjplsdir) libcharlslibdir = -L$(dcmjplsdir)/libcharls -libcharlslib = -lcharls +libcharlslib = -ldcmtkcharls LOCALINCLUDES = $(dcmjplsinc) $(ofstdinc) $(ofloginc) $(dcmdatainc) $(dcmimageinc) $(dcmimgleinc) LIBDIRS = -L$(top_srcdir)/libsrc $(dcmjplslibdir) $(libcharlslibdir) $(dcmimagelibdir) \ diff --git a/dcmjpls/apps/dcmcjpls.cc b/dcmjpls/apps/dcmcjpls.cc index 9e958d53..b1f3eafe 100644 --- a/dcmjpls/apps/dcmcjpls.cc +++ b/dcmjpls/apps/dcmcjpls.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2019, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -152,7 +152,9 @@ LICENSE_FILE_DECLARE_COMMAND_LINE_OPTIONS cmd.addSubGroup("JPEG-LS interleave:"); cmd.addOption("--interleave-line", "+il", "force line-interleaved JPEG-LS images (default)"); cmd.addOption("--interleave-sample", "+is", "force sample-interleaved JPEG-LS images"); +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE cmd.addOption("--interleave-none", "+in", "force uninterleaved JPEG-LS images"); +#endif cmd.addOption("--interleave-default", "+iv", "use the fastest possible interleave mode"); cmd.addSubGroup("JPEG-LS padding of odd-length bitstreams:"); cmd.addOption("--padding-standard", "+ps", "pad with extended EOI marker (default)"); @@ -321,10 +323,12 @@ LICENSE_FILE_EVALUATE_COMMAND_LINE_OPTIONS { opt_interleaveMode = DJLSCodecParameter::interleaveLine; } +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE if (cmd.findOption("--interleave-none")) { opt_interleaveMode = DJLSCodecParameter::interleaveNone; } +#endif cmd.endOptionBlock(); // padding diff --git a/dcmjpls/apps/dcmdjpls.cc b/dcmjpls/apps/dcmdjpls.cc index 006ddad3..df0ac974 100644 --- a/dcmjpls/apps/dcmdjpls.cc +++ b/dcmjpls/apps/dcmdjpls.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2019, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) OFCmdUnsignedInt opt_filepad = 0; OFCmdUnsignedInt opt_itempad = 0; E_FileReadMode opt_readMode = ERM_autoDetect; - E_FileWriteMode opt_writeMode = EWM_fileformat; + E_FileWriteMode opt_writeMode = EWM_createNewMeta; E_TransferSyntax opt_ixfer = EXS_Unknown; OFBool opt_forceSingleFragmentPerFrame = OFFalse; @@ -212,7 +212,7 @@ LICENSE_FILE_EVALUATE_COMMAND_LINE_OPTIONS cmd.endOptionBlock(); cmd.beginOptionBlock(); - if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-file")) opt_writeMode = EWM_createNewMeta; if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; cmd.endOptionBlock(); @@ -315,10 +315,6 @@ LICENSE_FILE_EVALUATE_COMMAND_LINE_OPTIONS OFLOG_INFO(dcmdjplsLogger, "creating output file " << opt_ofname); - // update file meta information with new SOP Instance UID - if (opt_uidcreation && (opt_writeMode == EWM_fileformat)) - opt_writeMode = EWM_updateMeta; - fileformat.loadAllDataIntoMemory(); error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); diff --git a/dcmjpls/docs/dcmcjpls.man b/dcmjpls/docs/dcmcjpls.man index b5180db7..bf16e4c3 100644 --- a/dcmjpls/docs/dcmcjpls.man +++ b/dcmjpls/docs/dcmcjpls.man @@ -162,13 +162,6 @@ JPEG-LS interleave: # In sample-interleave mode each pixel's components are encoded before # the next pixel is encoded. - +in --interleave-none - force uninterleaved JPEG-LS images - - # This flag forces uninterleaved mode for the resulting image. - # In this mode, each of the image's components are completely encoded - # before the next component is handled. - +iv --interleave-default use the fastest possible interleave mode @@ -395,6 +388,6 @@ It is an error if no data dictionary can be loaded. \section dcmcjpls_copyright COPYRIGHT -Copyright (C) 2009-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2009-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmjpls/docs/dcmjpls.dox b/dcmjpls/docs/dcmjpls.dox index 9db860a5..1cee5fa7 100644 --- a/dcmjpls/docs/dcmjpls.dox +++ b/dcmjpls/docs/dcmjpls.dox @@ -41,11 +41,6 @@ if (fileformat.loadFile("test.dcm").good()) // check if everything went well if (dataset->canWriteXfer(EXS_JPEGLSLossless)) { - // force the meta-header UIDs to be re-generated when storing the file - // since the UIDs in the data set may have changed - delete metaInfo->remove(DCM_MediaStorageSOPClassUID); - delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID); - // store in lossless JPEG-LS format fileformat.saveFile("test_jpls.dcm", EXS_JPEGLSLossless); } @@ -76,12 +71,12 @@ DJLSDecoderRegistration::cleanup(); // deregister JPEG-LS codecs \section Legal Legal Remark -Please note that Hewlett Packard claims to own patents that apply to -JPEG-LS. Hewlett Packard grants free licenses for conformant -implementations of JPEG-LS. OFFIS as the author of the DCMTK toolkit -has obtained such a license, but depending on your national -legislations companies that use DCMTK's JPEG-LS codec may need to -also acquire a license. Read more at http://www.hpl.hp.com/loco/ if +Please note that Hewlett Packard claims to own patents that apply to +JPEG-LS. Hewlett Packard grants free licenses for conformant +implementations of JPEG-LS. OFFIS as the author of the DCMTK toolkit +has obtained such a license, but depending on your national +legislations companies that use DCMTK's JPEG-LS codec may need to +also acquire a license. Read more at http://www.hpl.hp.com/loco/ if you intend to use this module for commercial purposes. */ diff --git a/dcmjpls/docs/dcml2pnm.man b/dcmjpls/docs/dcml2pnm.man index a5044f4e..e9b37967 100644 --- a/dcmjpls/docs/dcml2pnm.man +++ b/dcmjpls/docs/dcml2pnm.man @@ -127,7 +127,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -328,7 +328,7 @@ PNG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -498,6 +498,6 @@ It is an error if no data dictionary can be loaded. \section dcml2pnm_copyright COPYRIGHT -Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2001-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h b/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h index 71c5de79..611d9b4d 100644 --- a/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h +++ b/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2017, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -54,6 +54,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -61,7 +65,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -111,6 +116,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -119,7 +128,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -133,6 +143,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -142,7 +156,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcodece.h b/dcmjpls/include/dcmtk/dcmjpls/djcodece.h index e2dbc4f8..01209c25 100644 --- a/dcmjpls/include/dcmtk/dcmjpls/djcodece.h +++ b/dcmjpls/include/dcmtk/dcmjpls/djcodece.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2019, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -57,6 +57,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition decode( @@ -64,7 +68,8 @@ public: DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const; + const DcmStack & objStack, + OFBool& removeOldRep) const; /** decompresses a single frame from the given pixel sequence and * stores the result in the given buffer. @@ -114,6 +119,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -122,7 +131,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** transcodes (re-compresses) the given compressed DICOM image and stores * the result in the given toPixSeq element. @@ -136,6 +146,10 @@ public: * @param cp codec parameters for this codec * @param objStack stack pointing to the location of the pixel data * element in the current dataset. + * @param removeOldRep boolean flag that should be set to false before this method call + * and will be set to true if the codec modifies the DICOM dataset such + * that the pixel data of the original representation may not be usable + * anymore. * @return EC_Normal if successful, an error code otherwise. */ virtual OFCondition encode( @@ -145,7 +159,8 @@ public: const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & toPixSeq, const DcmCodecParameter * cp, - DcmStack & objStack) const; + DcmStack & objStack, + OFBool& removeOldRep) const; /** checks if this codec is able to convert from the * given current transfer syntax to the given new diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcparam.h b/dcmjpls/include/dcmtk/dcmjpls/djcparam.h index 524fd736..cce6ca42 100644 --- a/dcmjpls/include/dcmtk/dcmjpls/djcparam.h +++ b/dcmjpls/include/dcmtk/dcmjpls/djcparam.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2019, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -42,9 +42,12 @@ public: /// Sample-interleaved (color-by-pixel) interleaveSample, /// Line-interleaved (color-by-line) - interleaveLine, + interleaveLine +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE + , /// Uninterleaved (color-by-plane) interleaveNone +#endif }; /** constructor, for use with encoders. diff --git a/dcmjpls/libcharls/CMakeLists.txt b/dcmjpls/libcharls/CMakeLists.txt index 0c5b1433..ae0c0172 100644 --- a/dcmjpls/libcharls/CMakeLists.txt +++ b/dcmjpls/libcharls/CMakeLists.txt @@ -2,6 +2,6 @@ include_directories("${dcmjpls_SOURCE_DIR}/libcharls" "${ofstd_SOURCE_DIR}/include") # create library from source files -DCMTK_ADD_LIBRARY(charls header intrface jpegls) +DCMTK_ADD_LIBRARY(dcmtkcharls header intrface jpegls) -DCMTK_TARGET_LINK_MODULES(charls ofstd oflog) +DCMTK_TARGET_LINK_MODULES(dcmtkcharls ofstd oflog) diff --git a/dcmjpls/libcharls/Makefile.in b/dcmjpls/libcharls/Makefile.in index d26877c4..a6f1f467 100644 --- a/dcmjpls/libcharls/Makefile.in +++ b/dcmjpls/libcharls/Makefile.in @@ -19,7 +19,7 @@ LOCALDEFS = objs = header.o intrface.o jpegls.o -library = libcharls.$(LIBEXT) +library = libdcmtkcharls.$(LIBEXT) all: $(library) diff --git a/dcmjpls/libcharls/header.cc b/dcmjpls/libcharls/header.cc index 8e9a0504..8c8cd521 100644 --- a/dcmjpls/libcharls/header.cc +++ b/dcmjpls/libcharls/header.cc @@ -1,6 +1,6 @@ -// -// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. -// +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// #include "config.h" #include "util.h" @@ -68,12 +68,12 @@ JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams) switch (pparams->components) { - case 4: return pparams->ilv == ILV_SAMPLE ? ParameterValueNotSupported : OK; + case 4: return pparams->ilv == ILV_SAMPLE ? ParameterValueNotSupported : OK; case 3: return OK; case 1: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK; case 0: return InvalidJlsParameters; - default: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK; + default: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK; } } @@ -94,7 +94,7 @@ public: pstream->WriteByte(0xFF); pstream->WriteByte(_marker); pstream->WriteWord(USHORT(_vecbyte.size() + 2)); - pstream->WriteBytes(_vecbyte); + pstream->WriteBytes(_vecbyte); } BYTE _marker; @@ -109,7 +109,7 @@ void push_back(OFVector& vec, USHORT value) { vec.push_back(BYTE(value / 0x100)); vec.push_back(BYTE(value % 0x100)); -} +} // @@ -122,16 +122,16 @@ JpegSegment* CreateMarkerStartOfFrame(Size size, LONG bitsPerSample, LONG ccomp) vec.push_back(static_cast(bitsPerSample)); push_back(vec, static_cast(size.cy)); push_back(vec, static_cast(size.cx)); - + // components vec.push_back(static_cast(ccomp)); for (BYTE component = 0; component < ccomp; component++) { // rescaling vec.push_back(component + 1); - vec.push_back(0x11); + vec.push_back(0x11); //"Tq1" reserved, 0 - vec.push_back(0); + vec.push_back(0); } return new JpegMarkerSegment(JPEG_SOF, vec); @@ -161,7 +161,6 @@ JLSOutputStream::~JLSOutputStream() { delete _segments[i]; } - _segments.empty(); } @@ -172,7 +171,7 @@ JLSOutputStream::~JLSOutputStream() // void JLSOutputStream::Init(Size size, LONG bitsPerSample, LONG ccomp) { - _segments.push_back(CreateMarkerStartOfFrame(size, bitsPerSample, ccomp)); + _segments.push_back(CreateMarkerStartOfFrame(size, bitsPerSample, ccomp)); } @@ -184,8 +183,8 @@ void JLSOutputStream::AddColorTransform(int i) rgbyteXform.push_back('f'); rgbyteXform.push_back('x'); rgbyteXform.push_back((BYTE)i); - - _segments.push_back(new JpegMarkerSegment(JPEG_APP8, rgbyteXform)); + + _segments.push_back(new JpegMarkerSegment(JPEG_APP8, rgbyteXform)); } @@ -201,7 +200,7 @@ size_t JLSOutputStream::Write(BYTE **ptr, size_t *size, size_t offset) WriteByte(0xFF); WriteByte(JPEG_SOI); - + for (size_t i = 0; i < _segments.size(); ++i) { _segments[i]->Write(this); @@ -263,7 +262,7 @@ void JLSInputStream::ReadPixels(void* pvoid, size_t cbyteAvailable) if (cbyteAvailable < cbytePlane * _info.components) throw JlsException(UncompressedBufferTooSmall); - + int scancount = _info.ilv == ILV_NONE ? _info.components : 1; BYTE* pbyte = (BYTE*)pvoid; @@ -271,7 +270,7 @@ void JLSInputStream::ReadPixels(void* pvoid, size_t cbyteAvailable) { ReadScan(pbyte); pbyte += cbytePlane; - } + } } // ReadNBytes() @@ -295,7 +294,7 @@ void JLSInputStream::ReadHeader() if (ReadByte() != JPEG_SOI) throw JlsException(InvalidCompressedData); - + for (;;) { if (ReadByte() != 0xFF) @@ -314,13 +313,13 @@ void JLSInputStream::ReadHeader() case JPEG_LSE: ReadPresetParameters(); break; case JPEG_APP0: ReadJfif(); break; case JPEG_APP7: ReadColorSpace(); break; - case JPEG_APP8: ReadColorXForm(); break; + case JPEG_APP8: ReadColorXForm(); break; // Other tags not supported (among which DNL DRI) default: throw JlsException(ImageTypeNotSupported); } if (marker == JPEG_SOS) - { + { _cbyteOffset = cbyteStart - 2; return; } @@ -332,7 +331,7 @@ void JLSInputStream::ReadHeader() JpegMarkerSegment* EncodeStartOfScan(const JlsParameters* pparams, LONG icomponent) { BYTE itable = 0; - + OFVector rgbyte; if (icomponent < 0) @@ -348,7 +347,7 @@ JpegMarkerSegment* EncodeStartOfScan(const JlsParameters* pparams, LONG icompone { rgbyte.push_back(1); rgbyte.push_back((BYTE)icomponent); - rgbyte.push_back(itable); + rgbyte.push_back(itable); } rgbyte.push_back(BYTE(pparams->allowedlossyerror)); @@ -370,7 +369,7 @@ JpegMarkerSegment* CreateLSE(const JlsCustomParameters* pcustom) push_back(rgbyte, (USHORT)pcustom->T2); push_back(rgbyte, (USHORT)pcustom->T3); push_back(rgbyte, (USHORT)pcustom->RESET); - + return new JpegMarkerSegment(JPEG_LSE, rgbyte); } @@ -395,7 +394,7 @@ void JLSInputStream::ReadPresetParameters() } } - + } @@ -412,7 +411,7 @@ void JLSInputStream::ReadStartOfScan() } _info.allowedlossyerror = ReadByte(); _info.ilv = interleavemode(ReadByte()); - + if(_info.bytesperline == 0) { int width = _rect.Width != 0 ? _rect.Width : _info.width; @@ -446,11 +445,11 @@ void JLSInputStream::ReadJfif() _info.jfif.units = ReadByte(); _info.jfif.XDensity = ReadWord(); _info.jfif.YDensity = ReadWord(); - + // thumbnail _info.jfif.Xthumb = ReadByte(); _info.jfif.Ythumb = ReadByte(); - if(_info.jfif.Xthumb > 0 && _info.jfif.pdataThumbnail) + if(_info.jfif.Xthumb > 0 && _info.jfif.pdataThumbnail) { OFVector tempbuff((char*)_info.jfif.pdataThumbnail, (char*)_info.jfif.pdataThumbnail+3*_info.jfif.Xthumb*_info.jfif.Ythumb); ReadNBytes(tempbuff, 3*_info.jfif.Xthumb*_info.jfif.Ythumb); @@ -471,14 +470,14 @@ JpegMarkerSegment* CreateJFIF(const JfifParameters* jfif) push_back(rgbyte, (USHORT)jfif->Ver); - rgbyte.push_back(jfif->units); + rgbyte.push_back(jfif->units); push_back(rgbyte, (USHORT)jfif->XDensity); push_back(rgbyte, (USHORT)jfif->YDensity); // thumbnail rgbyte.push_back((BYTE)jfif->Xthumb); rgbyte.push_back((BYTE)jfif->Ythumb); - if(jfif->Xthumb > 0) + if(jfif->Xthumb > 0) { if(jfif->pdataThumbnail) throw JlsException(InvalidJlsParameters); @@ -486,7 +485,7 @@ JpegMarkerSegment* CreateJFIF(const JfifParameters* jfif) rgbyte.insert(rgbyte.end(), (BYTE*)jfif->pdataThumbnail, (BYTE*)jfif->pdataThumbnail+3*jfif->Xthumb*jfif->Ythumb ); } - + return new JpegMarkerSegment(JPEG_APP0, rgbyte); } @@ -509,11 +508,11 @@ void JLSInputStream::ReadStartOfFrame() // ReadByte() // BYTE JLSInputStream::ReadByte() -{ +{ if (_cbyteOffset >= _cbyteLength) throw JlsException(InvalidCompressedData); - return _pdata[_cbyteOffset++]; + return _pdata[_cbyteOffset++]; } @@ -527,10 +526,10 @@ int JLSInputStream::ReadWord() } -void JLSInputStream::ReadScan(void* pvout) +void JLSInputStream::ReadScan(void* pvout) { OFunique_ptr qcodec = JlsCodecFactory().GetCodec(_info, _info.custom); - + BYTE **ptr = (BYTE **)&_pdata; size_t *size = &_cbyteLength; _cbyteOffset += qcodec->DecodeScan(pvout, _rect, ptr, size, _cbyteOffset, _bCompare); @@ -549,9 +548,9 @@ public: } void Write(JLSOutputStream* pstream) - { + { JlsParameters info = _info; - info.components = _ccompScan; + info.components = _ccompScan; OFunique_ptr qcodec =JlsCodecFactory().GetCodec(info, _info.custom); size_t cbyteWritten = qcodec->EncodeScan((BYTE*)_pvoidRaw, pstream->get_pos(), pstream->get_size(), pstream->get_offset(), pstream->_bCompare); pstream->seek(cbyteWritten); @@ -573,7 +572,7 @@ void JLSOutputStream::AddScan(const void* compareData, const JlsParameters* ppar } if (!IsDefault(&pparams->custom)) { - _segments.push_back(CreateLSE(&pparams->custom)); + _segments.push_back(CreateLSE(&pparams->custom)); } else if (pparams->bitspersample > 12) { @@ -608,9 +607,9 @@ void JLSInputStream::ReadColorXForm() if(strncmp(&sourceTag[0],"mrfx", 4) != 0) return; - + int xform = ReadByte(); - switch(xform) + switch(xform) { case COLORXFORM_NONE: case COLORXFORM_HP1: @@ -625,4 +624,3 @@ void JLSInputStream::ReadColorXForm() throw JlsException(InvalidCompressedData); } } - diff --git a/dcmjpls/libcharls/intrface.h b/dcmjpls/libcharls/intrface.h index c8fdaa90..3aa27fdc 100644 --- a/dcmjpls/libcharls/intrface.h +++ b/dcmjpls/libcharls/intrface.h @@ -10,7 +10,7 @@ #include "dcmtk/ofstd/ofstd.h" /* for size_t */ #include "dcmtk/ofstd/ofdefine.h" /* for DCMTK_DECL_EXPORT */ -#ifdef charls_EXPORTS +#ifdef dcmtkcharls_EXPORTS #define DCMTK_CHARLS_EXPORT DCMTK_DECL_EXPORT #else #define DCMTK_CHARLS_EXPORT DCMTK_DECL_IMPORT diff --git a/dcmjpls/libsrc/CMakeLists.txt b/dcmjpls/libsrc/CMakeLists.txt index 314face7..bd928f82 100644 --- a/dcmjpls/libsrc/CMakeLists.txt +++ b/dcmjpls/libsrc/CMakeLists.txt @@ -4,4 +4,4 @@ include_directories("${dcmjpls_SOURCE_DIR}/include" "${ofstd_SOURCE_DIR}/include # create library from source files DCMTK_ADD_LIBRARY(dcmjpls djcparam djdecode djencode djrparam djcodecd djutils djcodece) -DCMTK_TARGET_LINK_MODULES(dcmjpls ofstd oflog dcmdata dcmimgle dcmimage charls) +DCMTK_TARGET_LINK_MODULES(dcmjpls ofstd oflog dcmdata dcmimgle dcmimage dcmtkcharls) diff --git a/dcmjpls/libsrc/djcodecd.cc b/dcmjpls/libsrc/djcodecd.cc index 4b3b2390..fc0df5c7 100644 --- a/dcmjpls/libsrc/djcodecd.cc +++ b/dcmjpls/libsrc/djcodecd.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2019, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -81,8 +81,16 @@ OFCondition DJLSDecoderBase::decode( DcmPixelSequence * pixSeq, DcmPolymorphOBOW& uncompressedPixelData, const DcmCodecParameter * cp, - const DcmStack& objStack) const + const DcmStack& objStack, + OFBool& removeOldRep) const { + + // this codec may modify the DICOM header such that the previous pixel + // representation is not valid anymore, e.g. in the case of color images + // where the planar configuration can change. Indicate this to the caller + // to trigger removal. + removeOldRep = OFTrue; + // retrieve pointer to dataset from parameter stack DcmStack localStack(objStack); (void)localStack.pop(); // pop pixel data element from stack @@ -470,7 +478,8 @@ OFCondition DJLSDecoderBase::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* pixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we are a decoder only return EC_IllegalCall; @@ -484,7 +493,8 @@ OFCondition DJLSDecoderBase::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack & /* objStack */, + OFBool& /* removeOldRep */) const { // we don't support re-coding for now. return EC_IllegalCall; diff --git a/dcmjpls/libsrc/djcodece.cc b/dcmjpls/libsrc/djcodece.cc index 1370fee7..5e826627 100644 --- a/dcmjpls/libsrc/djcodece.cc +++ b/dcmjpls/libsrc/djcodece.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2007-2019, OFFIS e.V. + * Copyright (C) 2007-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -108,7 +108,8 @@ OFCondition DJLSEncoderBase::decode( DcmPixelSequence * /* pixSeq */, DcmPolymorphOBOW& /* uncompressedPixelData */, const DcmCodecParameter * /* cp */, - const DcmStack& /* objStack */) const + const DcmStack& /* objStack */, + OFBool& /* removeOldRep */ ) const { // we are an encoder only return EC_IllegalCall; @@ -138,7 +139,8 @@ OFCondition DJLSEncoderBase::encode( const DcmRepresentationParameter * /* toRepParam */, DcmPixelSequence * & /* toPixSeq */, const DcmCodecParameter * /* cp */, - DcmStack & /* objStack */) const + DcmStack& /* objStack */, + OFBool& /* removeOldRep */ ) const { // we don't support re-coding for now. return EC_IllegalCall; @@ -150,11 +152,17 @@ OFCondition DJLSEncoderBase::encode( const DcmRepresentationParameter * toRepParam, DcmPixelSequence * & pixSeq, const DcmCodecParameter *cp, - DcmStack & objStack) const + DcmStack& objStack, + OFBool& removeOldRep) const { OFCondition result = EC_Normal; DJLSRepresentationParameter defRep; + // this codec may modify the DICOM header such that the previous pixel + // representation is not valid anymore. Indicate this to the caller + // to trigger removal. + removeOldRep = OFTrue; + // retrieve pointer to dataset from parameter stack DcmStack localStack(objStack); (void)localStack.pop(); // pop pixel data element from stack @@ -685,14 +693,20 @@ OFCondition DJLSEncoderBase::compressRawFrame( case DJLSCodecParameter::interleaveLine: jls_params.ilv = ILV_LINE; break; +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE case DJLSCodecParameter::interleaveNone: jls_params.ilv = ILV_NONE; break; +#endif case DJLSCodecParameter::interleaveDefault: default: // In default mode we just never convert the image to another // interleave-mode. Instead, we use what is already there. +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE jls_params.ilv = ilv; +#else + jls_params.ilv = (ilv == ILV_NONE ? ILV_LINE : ilv); +#endif break; } @@ -1099,9 +1113,11 @@ OFCondition DJLSEncoderBase::compressCookedFrame( case DJLSCodecParameter::interleaveLine: jls_params.ilv = ILV_LINE; break; +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE case DJLSCodecParameter::interleaveNone: jls_params.ilv = ILV_NONE; break; +#endif case DJLSCodecParameter::interleaveDefault: default: // Default for the cooked encoder is always ILV_LINE @@ -1117,6 +1133,8 @@ OFCondition DJLSEncoderBase::compressCookedFrame( Uint8 *frameBuffer = NULL; Uint8 *framePointer = buffer; + +#ifdef ENABLE_DCMJPLS_INTERLEAVE_NONE // Do we have to convert the image to color-by-plane now? if (jls_params.ilv == ILV_NONE && jls_params.components != 1) { @@ -1126,6 +1144,7 @@ OFCondition DJLSEncoderBase::compressCookedFrame( framePointer = frameBuffer; result = convertToUninterleaved(frameBuffer, buffer, samplesPerPixel, width, height, jls_params.bitspersample); } +#endif size_t compressed_buffer_size = buffer_size + 1024; BYTE *compressed_buffer = new BYTE[compressed_buffer_size]; diff --git a/dcmnet/apps/CMakeLists.txt b/dcmnet/apps/CMakeLists.txt index aa0ff8b2..6ab669f2 100644 --- a/dcmnet/apps/CMakeLists.txt +++ b/dcmnet/apps/CMakeLists.txt @@ -29,7 +29,7 @@ endif() foreach(PROGRAM dcmrecv dcmsend echoscu findscu getscu movescu storescp storescu termscu) DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmnet dcmdata oflog ofstd) endforeach() -foreach(PROGRAM echoscu findscu storescp storescu) +foreach(PROGRAM dcmrecv echoscu findscu storescp storescu) DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmtls) endforeach() diff --git a/dcmnet/apps/Makefile.dep b/dcmnet/apps/Makefile.dep index 4f10a025..167ad9d0 100644 --- a/dcmnet/apps/Makefile.dep +++ b/dcmnet/apps/Makefile.dep @@ -27,6 +27,8 @@ dcmrecv.o: dcmrecv.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ ../include/dcmtk/dcmnet/dstorscp.h \ ../../ofstd/include/dcmtk/ofstd/offname.h ../include/dcmtk/dcmnet/scp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -51,8 +53,6 @@ dcmrecv.o: dcmrecv.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ @@ -125,12 +125,12 @@ dcmrecv.o: dcmrecv.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h dcmsend.o: dcmsend.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ @@ -252,17 +252,17 @@ dcmsend.o: dcmsend.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ - ../include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ - ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dndefine.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/assoc.h \ ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ - ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ - ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ - ../include/dcmtk/dcmnet/dntypes.h ../include/dcmtk/dcmnet/assoc.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ + ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ + ../include/dcmtk/dcmnet/dimse.h \ ../../dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h \ ../../dcmjpeg/include/dcmtk/dcmjpeg/djutils.h \ ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ @@ -553,17 +553,17 @@ getscu.o: getscu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ - ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dndefine.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/assoc.h \ ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ - ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ - ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ - ../include/dcmtk/dcmnet/dntypes.h ../include/dcmtk/dcmnet/assoc.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ + ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ + ../include/dcmtk/dcmnet/dimse.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpath.h movescu.o: movescu.cc ../../config/include/dcmtk/config/osconfig.h \ diff --git a/dcmnet/apps/Makefile.in b/dcmnet/apps/Makefile.in index 765e1dd1..625c39c0 100644 --- a/dcmnet/apps/Makefile.in +++ b/dcmnet/apps/Makefile.in @@ -32,7 +32,7 @@ LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ LOCALLIBS = -ldcmnet -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(TCPWRAPPERLIBS) \ $(CHARCONVLIBS) $(MATHLIBS) DCMTLSLIBS = -ldcmtls -COMPR_LIBS = -ldcmjpls -lcharls -ldcmjpeg -lijg8 -lijg12 -lijg16 -ldcmimage -ldcmimgle +COMPR_LIBS = -ldcmjpls -ldcmtkcharls -ldcmjpeg -lijg8 -lijg12 -lijg16 -ldcmimage -ldcmimgle objs = echoscu.o storescu.o storescp.o findscu.o movescu.o termscu.o getscu.o dcmsend.o \ dcmrecv.o @@ -68,7 +68,7 @@ dcmsend: dcmsend.o $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(COMPR_LIBS) $(LOCALLIBS) $(TIFFLIBS) $(PNGLIBS) $(LIBS) dcmrecv: dcmrecv.o - $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS) + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(LIBS) install: all $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) diff --git a/dcmnet/apps/dcmrecv.cc b/dcmnet/apps/dcmrecv.cc index 408581f8..1e400019 100644 --- a/dcmnet/apps/dcmrecv.cc +++ b/dcmnet/apps/dcmrecv.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2013-2018, OFFIS e.V. + * Copyright (C) 2013-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -29,6 +29,7 @@ #include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ #include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ #include "dcmtk/dcmnet/dstorscp.h" /* for DcmStorageSCP */ +#include "dcmtk/dcmtls/tlsopt.h" /* for DcmTLSOptions */ /* general definitions */ @@ -51,6 +52,7 @@ static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" #define EXITCODE_CANNOT_INITIALIZE_NETWORK 60 // placeholder, currently not used #define EXITCODE_CANNOT_START_SCP_AND_LISTEN 64 #define EXITCODE_INVALID_ASSOCIATION_CONFIG 66 +#define EXITCODE_CANNOT_CREATE_TRANSPORT_LAYER 71 /* helper macro for converting stream output to a string */ @@ -68,7 +70,13 @@ static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" int main(int argc, char *argv[]) { + +#ifdef WITH_OPENSSL + DcmTLSTransportLayer::initializeOpenSSL(); +#endif + OFOStringStream optStream; + DcmTLSOptions tlsOptions(NET_ACCEPTOR); const char *opt_configFile = NULL; const char *opt_profileName = NULL; @@ -122,6 +130,10 @@ int main(int argc, char *argv[]) cmd.addOption("--max-pdu", "-pdu", 1, optString3.c_str(), optString4.c_str()); cmd.addOption("--disable-host-lookup", "-dhl", "disable hostname lookup"); + + /* add TLS specific command line options if (and only if) we are compiling with OpenSSL */ + tlsOptions.addTLSCommandlineOptions(cmd); + cmd.addGroup("output options:"); cmd.addSubGroup("general:"); CONVERT_TO_STRING("[d]irectory: string (default: \"" << opt_outputDirectory << "\")", optString5); @@ -152,9 +164,23 @@ int main(int argc, char *argv[]) if (cmd.findOption("--version")) { app.printHeader(OFTrue /*print host identifier*/); - COUT << OFendl << "External libraries used: none" << OFendl; + COUT << OFendl << "External libraries used:"; +#ifdef WITH_OPENSSL + COUT << OFendl; + tlsOptions.printLibraryVersion(); +#else + COUT << " none" << OFendl; +#endif return EXITCODE_NO_ERROR; } + + /* check if the command line contains the --list-ciphers option */ + if (tlsOptions.listOfCiphersRequested(cmd)) + { + tlsOptions.printSupportedCiphersuites(app, COUT); + return EXITCODE_NO_ERROR; + } + } /* general options */ @@ -233,6 +259,9 @@ int main(int argc, char *argv[]) /* command line parameters */ app.checkParam(cmd.getParamAndCheckMinMax(1, opt_port, 1, 65535)); + + /* evaluate (most of) the TLS command line options (if we are compiling with OpenSSL) */ + tlsOptions.parseArguments(app, cmd); } /* print resource identifier */ @@ -290,6 +319,18 @@ int main(int argc, char *argv[]) OFLOG_INFO(dcmrecvLogger, "starting service class provider and listening ..."); + /* create a secure transport layer if requested and OpenSSL is available */ + status = tlsOptions.createTransportLayer(NULL, NULL, app, cmd); + if (status.bad()) + { + OFString tempStr; + OFLOG_FATAL(dcmrecvLogger, DimseCondition::dump(tempStr, status)); + return EXITCODE_CANNOT_CREATE_TRANSPORT_LAYER; + } + + if (tlsOptions.secureConnectionRequested()) + storageSCP.getConfig().setTransportLayer(tlsOptions.getTransportLayer()); + /* start SCP and listen on the specified port */ status = storageSCP.listen(); if (status.bad()) diff --git a/dcmnet/apps/findscu.cc b/dcmnet/apps/findscu.cc index fcd9e965..da3e5d0a 100644 --- a/dcmnet/apps/findscu.cc +++ b/dcmnet/apps/findscu.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -23,6 +23,7 @@ #include "dcmtk/dcmnet/dfindscu.h" #include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmnet/dcmtrans.h" /* for dcmSocketSend/ReceiveTimeout */ #include "dcmtk/dcmdata/cmdlnarg.h" #include "dcmtk/ofstd/ofconapp.h" #include "dcmtk/dcmdata/dcdict.h" @@ -47,15 +48,24 @@ static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" #define APPLICATIONTITLE "FINDSCU" #define PEERAPPLICATIONTITLE "ANY-SCP" +/* helper macro for converting stream output to a string */ +#define CONVERT_TO_STRING(output, string) \ + optStream.str(""); \ + optStream.clear(); \ + optStream << output << OFStringStream_ends; \ + OFSTRINGSTREAM_GETOFSTRING(optStream, string) + #define SHORTCOL 4 #define LONGCOL 20 int main(int argc, char *argv[]) { + OFOStringStream optStream; OFList fileNameList; OFBool opt_abortAssociation = OFFalse; const char * opt_abstractSyntax = UID_FINDModalityWorklistInformationModel; int opt_acse_timeout = 30; + OFCmdSignedInt opt_socket_timeout = 60; T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; OFCmdSignedInt opt_cancelAfterNResponses = -1; int opt_dimse_timeout = 0; @@ -63,6 +73,7 @@ int main(int argc, char *argv[]) DcmFindSCUExtractMode opt_extractResponses = FEM_none; OFString opt_extractXMLFilename; OFString opt_outputDirectory = "."; + OFCmdUnsignedInt opt_limitOutputToNResponses = 0; OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; E_TransferSyntax opt_networkTransferSyntax = EXS_Unknown; const char * opt_ourTitle = APPLICATIONTITLE; @@ -88,7 +99,6 @@ int main(int argc, char *argv[]) DcmTLSTransportLayer::initializeOpenSSL(); #endif - char tempstr[20]; OFString temp_str; OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM query (C-FIND) SCU", rcsid); OFCommandLine cmd; @@ -114,14 +124,8 @@ int main(int argc, char *argv[]) cmd.addOption("--study", "-S", "use study root information model"); cmd.addOption("--psonly", "-O", "use patient/study only information model"); cmd.addSubGroup("application entity titles:"); - OFString opt1 = "set my calling AE title (default: "; - opt1 += APPLICATIONTITLE; - opt1 += ")"; - cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); - OFString opt2 = "set called AE title of peer (default: "; - opt2 += PEERAPPLICATIONTITLE; - opt2 += ")"; - cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", "set my calling AE title (default: " APPLICATIONTITLE ")"); + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", "set called AE title of peer (default: " PEERAPPLICATIONTITLE ")"); cmd.addSubGroup("post-1993 value representations:"); cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); @@ -139,21 +143,15 @@ int main(int argc, char *argv[]) "0=uncompressed, 1=fastest, 9=best compression"); #endif cmd.addSubGroup("other network options:"); - OFString opt3 = "set max receive pdu to n bytes (default: "; - sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); - opt3 += tempstr; - opt3 += ")"; - OFString opt4 = "[n]umber of bytes: integer ("; - sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); - opt4 += tempstr; - opt4 += ".."; - sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); - opt4 += tempstr; - opt4 += ")"; cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); - cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + CONVERT_TO_STRING("[s]econds: integer (default: " << opt_socket_timeout << ")", optString1); + cmd.addOption("--socket-timeout", "-ts", 1, optString1.c_str(), "timeout for network socket (0 for none)"); + CONVERT_TO_STRING("[s]econds: integer (default: " << opt_acse_timeout << ")", optString2); + cmd.addOption("--acse-timeout", "-ta", 1, optString2.c_str(), "timeout for ACSE messages"); cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); - cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + CONVERT_TO_STRING("[n]umber of bytes: integer (" << ASC_MINIMUMPDUSIZE << ".." << ASC_MAXIMUMPDUSIZE << ")", optString3); + CONVERT_TO_STRING("set max receive pdu to n bytes (default: " << opt_maxReceivePDULength << ")", optString4); + cmd.addOption("--max-pdu", "-pdu", 1, optString3.c_str(), optString4.c_str()); cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); cmd.addOption("--abort", "abort association instead of releasing it"); cmd.addOption("--cancel", 1, "[n]umber: integer", @@ -176,6 +174,8 @@ int main(int argc, char *argv[]) cmd.addOption("--extract-xml", "-Xx", "extract responses to XML file (rsp0001.xml...)"); cmd.addOption("--extract-xml-single", "-Xs", 1, "[f]ilename: string", "extract all responses to given XML file f"); + cmd.addOption("--limit-output", "-Xlo", 1, "[n]umber: integer", + "limit number of responses extracted to file to n\n(default: unlimited)"); /* evaluate command line */ prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); @@ -269,6 +269,12 @@ int main(int argc, char *argv[]) dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); } + if (cmd.findOption("--socket-timeout")) + app.checkValue(cmd.getValueAndCheckMin(opt_socket_timeout, -1)); + // always set the timeout values since the global default might be different + dcmSocketSendTimeout.set(OFstatic_cast(Sint32, opt_socket_timeout)); + dcmSocketReceiveTimeout.set(OFstatic_cast(Sint32, opt_socket_timeout)); + if (cmd.findOption("--acse-timeout")) { OFCmdSignedInt opt_timeout = 0; @@ -310,6 +316,11 @@ int main(int argc, char *argv[]) app.checkValue(cmd.getValue(opt_extractXMLFilename)); } cmd.endOptionBlock(); + if (cmd.findOption("--limit-output")) + { + app.checkDependence("--limit-output", "--extract, --extract-xml or --extract-xml-single", opt_extractResponses != FEM_none); + app.checkValue(cmd.getValueAndCheckMin(opt_limitOutputToNResponses, 1)); + } /* finally parse filenames */ int paramCount = cmd.getParamCount(); @@ -420,6 +431,9 @@ int main(int argc, char *argv[]) } #endif + // set further parameters + findscu.setOutputResponseLimit(opt_limitOutputToNResponses); + // do the main work: negotiate network association, perform C-FIND transaction, // process results, and finally tear down the association. cond = findscu.performQuery( diff --git a/dcmnet/apps/movescu.cc b/dcmnet/apps/movescu.cc index 7c406046..eadbcc42 100644 --- a/dcmnet/apps/movescu.cc +++ b/dcmnet/apps/movescu.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -1374,7 +1374,7 @@ storeSCPCallback( OFCondition cond = cbdata->dcmff->saveFile(ofname.c_str(), xfer, opt_sequenceType, opt_groupLength, opt_paddingType, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), - (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); + (opt_useMetaheader) ? EWM_createNewMeta : EWM_dataset); if (cond.bad()) { OFLOG_ERROR(movescuLogger, "cannot write DICOM file: " << ofname); diff --git a/dcmnet/apps/storescp.cc b/dcmnet/apps/storescp.cc index db289225..78ff9608 100644 --- a/dcmnet/apps/storescp.cc +++ b/dcmnet/apps/storescp.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -147,11 +147,8 @@ OFBool opt_promiscuous = OFFalse; OFBool opt_correctUIDPadding = OFFalse; OFBool opt_inetd_mode = OFFalse; OFString callingAETitle; // calling application entity title will be stored here -OFString lastCallingAETitle; OFString calledAETitle; // called application entity title will be stored here -OFString lastCalledAETitle; OFString callingPresentationAddress; // remote hostname or IP address will be stored here -OFString lastCallingPresentationAddress; const char * opt_respondingAETitle = APPLICATIONTITLE; static OFString opt_outputDirectory = "."; // default: output directory equals "." E_SortStudyMode opt_sortStudyMode = ESM_None; // default: no sorting @@ -343,6 +340,9 @@ int main(int argc, char *argv[]) cmd.addOption("--padding-off", "-p", "no padding (default)"); cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", "align file on multiple of f bytes and items\non multiple of i bytes"); + cmd.addSubGroup("handling of defined length UN elements:"); + cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)"); + cmd.addOption("--convert-un", "+uc", "convert to real VR if known"); #ifdef WITH_ZLIB cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated/same):"); cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", @@ -354,7 +354,6 @@ int main(int argc, char *argv[]) cmd.addOption("--sort-on-study-uid", "-su", 1, "[p]refix: string", "sort studies using prefix p and the Study\nInstance UID"); cmd.addOption("--sort-on-patientname", "-sp", "sort studies using the Patient's Name and\na timestamp"); - cmd.addSubGroup("filename generation:"); cmd.addOption("--default-filenames", "-uf", "generate filename from instance UID (default)"); cmd.addOption("--unique-filenames", "+uf", "generate unique filenames"); @@ -789,6 +788,11 @@ int main(int argc, char *argv[]) } cmd.endOptionBlock(); + cmd.beginOptionBlock(); + if (cmd.findOption("--retain-un")) dcmEnableUnknownVRConversion.set(OFFalse); + if (cmd.findOption("--convert-un")) dcmEnableUnknownVRConversion.set(OFTrue); + cmd.endOptionBlock(); + #ifdef WITH_ZLIB if (cmd.findOption("--compression-level")) { @@ -1453,10 +1457,6 @@ static OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfigura } #endif - // store previous values for later use - lastCallingAETitle = callingAETitle; - lastCalledAETitle = calledAETitle; - lastCallingPresentationAddress = callingPresentationAddress; // store calling and called aetitle in global variables to enable // the --exec options using them. Enclose in quotation marks because // aetitles may contain space characters. @@ -2323,13 +2323,13 @@ static void executeOnEndOfStudy() cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), lastStudySubdirectoryPathAndName ); // perform substitution for placeholder #a - cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? callingAETitle : lastCallingAETitle ); + cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), callingAETitle ); // perform substitution for placeholder #c - cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? calledAETitle : lastCalledAETitle ); + cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), calledAETitle ); // perform substitution for placeholder #r - cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? callingPresentationAddress : lastCallingPresentationAddress ); + cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress ); // Execute command in a new process executeCommand( cmd ); @@ -2401,13 +2401,13 @@ static void executeCommand( const OFString &cmd ) } #else PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); // execute command (Attention: Do not pass DETACHED_PROCESS as sixth argument to the below // called function because in such a case the execution of batch-files is not going to work.) - if( !CreateProcess(NULL, OFconst_cast(char *, cmd.c_str()), NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo) ) + if( !CreateProcessA(NULL, OFconst_cast(char *, cmd.c_str()), NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo) ) OFLOG_ERROR(storescpLogger, "cannot execute command '" << cmd << "'"); if (opt_execSync) diff --git a/dcmnet/docs/dcmrecv.man b/dcmnet/docs/dcmrecv.man index ed437bfb..b36f34b0 100644 --- a/dcmnet/docs/dcmrecv.man +++ b/dcmnet/docs/dcmrecv.man @@ -90,6 +90,98 @@ other network options: -dhl --disable-host-lookup disable hostname lookup \endverbatim +\subsection dcmrecv_tls_options transport layer security (TLS) options +\verbatim +transport protocol stack: + + -tls --disable-tls + use normal TCP/IP connection (default) + + +tls --enable-tls [p]rivate key file, [c]ertificate file: string + use authenticated secure TLS connection + +private key password (only with --enable-tls): + + +ps --std-passwd + prompt user to type password on stdin (default) + + +pw --use-passwd [p]assword: string + use specified password + + -pw --null-passwd + use empty string as password + +key and certificate file format: + + -pem --pem-keys + read keys and certificates as PEM file (default) + + -der --der-keys + read keys and certificates as DER file + +certification authority: + + +cf --add-cert-file [f]ilename: string + add certificate file to list of certificates + + +cd --add-cert-dir [d]irectory: string + add certificates in d to list of certificates + +security profile: + + +px --profile-bcp195 + BCP 195 TLS Profile (default) + + +py --profile-bcp195-nd + Non-downgrading BCP 195 TLS Profile + + +pz --profile-bcp195-ex + Extended BCP 195 TLS Profile + + +pb --profile-basic + Basic TLS Secure Transport Connection Profile (retired) + + +pa --profile-aes + AES TLS Secure Transport Connection Profile (retired) + + +pn --profile-null + Authenticated unencrypted communication + (retired, was used in IHE ATNA) + +ciphersuite: + + +cc --list-ciphers + show list of supported TLS ciphersuites and exit + + +cs --cipher [c]iphersuite name: string + add ciphersuite to list of negotiated suites + + +dp --dhparam [f]ilename: string + read DH parameters for DH/DSS ciphersuites + +pseudo random generator: + + +rs --seed [f]ilename: string + seed random generator with contents of f + + +ws --write-seed + write back modified seed (only with --seed) + + +wf --write-seed-file [f]ilename: string (only with --seed) + write modified seed to file f + +peer authentication: + + -rc --require-peer-cert + verify peer certificate, fail if absent (default) + + -vc --verify-peer-cert + verify peer certificate if present + + -ic --ignore-peer-cert + don't verify peer certificate +\endverbatim + \subsection dcmrecv_output_options output options \verbatim general: @@ -323,6 +415,7 @@ EXITCODE_INVALID_OUTPUT_DIRECTORY 45 EXITCODE_CANNOT_INITIALIZE_NETWORK 60 (*) EXITCODE_CANNOT_START_SCP_AND_LISTEN 64 EXITCODE_INVALID_ASSOCIATION_CONFIG 66 +EXITCODE_CANNOT_CREATE_TRANSPORT_LAYER 71 \endverbatim (*) Actually, these codes are currently not used by \b dcmrecv but serve as a @@ -355,6 +448,6 @@ It is an error if no data dictionary can be loaded. \section dcmrecv_copyright COPYRIGHT -Copyright (C) 2013-2017 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2013-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/docs/echoscu.man b/dcmnet/docs/echoscu.man index 66ef9c22..ec451785 100644 --- a/dcmnet/docs/echoscu.man +++ b/dcmnet/docs/echoscu.man @@ -133,10 +133,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -294,6 +294,6 @@ It is an error if no data dictionary can be loaded. \section echoscu_copyright COPYRIGHT -Copyright (C) 1994-2018 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1994-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/docs/findscu.man b/dcmnet/docs/findscu.man index 74e9a007..2b717449 100644 --- a/dcmnet/docs/findscu.man +++ b/dcmnet/docs/findscu.man @@ -128,6 +128,9 @@ other network options: -to --timeout [s]econds: integer (default: unlimited) timeout for connection requests + -ts --socket-timeout [s]econds: integer (default: 60) + timeout for network socket (0 for none) + -ta --acse-timeout [s]econds: integer (default: 30) timeout for ACSE messages @@ -181,10 +184,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -267,6 +270,10 @@ C-FIND responses: -Xs --extract-xml-single [f]ilename: string extract all responses to given XML file f + + -Xlo --limit-output [n]umber: integer + limit number of responses extracted to file to n + (default: unlimited) \endverbatim \section findscu_notes NOTES @@ -448,6 +455,6 @@ It is an error if no data dictionary can be loaded. \section findscu_copyright COPYRIGHT -Copyright (C) 1994-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1994-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/docs/movescu.man b/dcmnet/docs/movescu.man index 5e3d08ad..fc8ec2f6 100644 --- a/dcmnet/docs/movescu.man +++ b/dcmnet/docs/movescu.man @@ -472,6 +472,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -526,6 +532,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -565,6 +572,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -584,6 +593,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -765,6 +781,6 @@ It is an error if no data dictionary can be loaded. \section movescu_copyright COPYRIGHT -Copyright (C) 1994-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1994-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/docs/storescp.man b/dcmnet/docs/storescp.man index 5ae53a20..13da0b40 100644 --- a/dcmnet/docs/storescp.man +++ b/dcmnet/docs/storescp.man @@ -241,10 +241,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -381,6 +381,14 @@ data set trailing padding align file on multiple of f bytes and items on multiple of i bytes +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known + deflate compression level (only with --write-xfer-deflated/same): +cl --compression-level [l]evel: integer (default: 6) @@ -628,6 +636,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -682,6 +696,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -721,6 +736,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -740,6 +757,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -912,6 +936,6 @@ It is an error if no data dictionary can be loaded. \section storescp_copyright COPYRIGHT -Copyright (C) 1996-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1996-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/docs/storescu.man b/dcmnet/docs/storescu.man index d4a25cf0..74746e67 100644 --- a/dcmnet/docs/storescu.man +++ b/dcmnet/docs/storescu.man @@ -323,10 +323,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -580,6 +580,6 @@ It is an error if no data dictionary can be loaded. \section storescu_copyright COPYRIGHT -Copyright (C) 1996-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1996-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmnet/etc/storescp.cfg b/dcmnet/etc/storescp.cfg index 6d83ff4e..2fba26e7 100644 --- a/dcmnet/etc/storescp.cfg +++ b/dcmnet/etc/storescp.cfg @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2019, OFFIS e.V. +# Copyright (C) 2003-2020, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by @@ -205,14 +205,21 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # # - AcquisitionContextSRStorage # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage # - BreastProjectionXRayImageStorageForPresentation # - BreastProjectionXRayImageStorageForProcessing +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage # - CompositingPlanarMPRVolumetricPresentationStateStorage # - ContentAssessmentResultsStorage # - CTDefinedProcedureProtocolStorage # - CTPerformedProcedureProtocolStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage # - ExtensibleSRStorage # - GrayscalePlanarMPRVolumetricPresentationStateStorage @@ -220,6 +227,7 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # - LegacyConvertedEnhancedCTImageStorage # - LegacyConvertedEnhancedMRImageStorage # - LegacyConvertedEnhancedPETImageStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -229,12 +237,20 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # - PlannedImagingAgentAdministrationSRStorage # - ProtocolApprovalStorage # - RadiopharmaceuticalRadiationDoseSRStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTBrachyApplicationSetupDeliveryInstructionStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage # - SimplifiedAdultEchoSRStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - TractographyResultsStorage # - VolumeRenderingVolumetricPresentationStateStorage # - WideFieldOphthalmicPhotographyStereographicProjectionImageStorage @@ -398,9 +414,17 @@ PresentationContext128 = XRayRadiationDoseSRStorage\UncompressedOrZlib # the following SOP classes are missing in the above list: # # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -408,10 +432,18 @@ PresentationContext128 = XRayRadiationDoseSRStorage\UncompressedOrZlib # - PerformedImagingAgentAdministrationSRStorage # - PlannedImagingAgentAdministrationSRStorage # - ProtocolApprovalStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - VolumeRenderingVolumetricPresentationStateStorage # # - RETIRED_HardcopyColorImageStorage diff --git a/dcmnet/etc/storescu.cfg b/dcmnet/etc/storescu.cfg index 252ff183..e915a09e 100644 --- a/dcmnet/etc/storescu.cfg +++ b/dcmnet/etc/storescu.cfg @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2019, OFFIS e.V. +# Copyright (C) 2003-2020, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by @@ -205,9 +205,11 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - AutorefractionMeasurementsStorage # - BasicStructuredDisplayStorage # - BlendingSoftcopyPresentationStateStorage +# - BodyPositionWaveformStorage # - BreastProjectionXRayImageStorageForPresentation # - BreastProjectionXRayImageStorageForProcessing # - BreastTomosynthesisImageStorage +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - CompositingPlanarMPRVolumetricPresentationStateStorage # - Comprehensive3DSRStorage @@ -216,7 +218,12 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - CTDefinedProcedureProtocolStorage # - CTPerformedProcedureProtocolStorage # - DeformableSpatialRegistrationStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage # - EncapsulatedCDAStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage # - EnhancedMRColorImageStorage # - EnhancedPETImageStorage @@ -237,6 +244,7 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - LegacyConvertedEnhancedPETImageStorage # - LensometryMeasurementsStorage # - MacularGridThicknessAndVolumeReportStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicAxialMeasurementsStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage @@ -252,21 +260,29 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - RadiopharmaceuticalRadiationDoseSRStorage # - RealWorldValueMappingStorage # - RespiratoryWaveformStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTBeamsDeliveryInstructionStorage # - RTBrachyApplicationSetupDeliveryInstructionStorage # - RTIonBeamsTreatmentRecordStorage # - RTIonPlanStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage # - SimplifiedAdultEchoSRStorage +# - SleepElectroencephalogramWaveformStorage # - SpectaclePrescriptionReportStorage # - SubjectiveRefractionMeasurementsStorage # - SurfaceScanMeshStorage # - SurfaceScanPointCloudStorage # - SurfaceSegmentationStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - TractographyResultsStorage # - VisualAcuityMeasurementsStorage # - VLWholeSlideMicroscopyImageStorage diff --git a/dcmnet/include/dcmtk/dcmnet/dfindscu.h b/dcmnet/include/dcmtk/dcmnet/dfindscu.h index 088aa072..76231def 100644 --- a/dcmnet/include/dcmtk/dcmnet/dfindscu.h +++ b/dcmnet/include/dcmtk/dcmnet/dfindscu.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -147,12 +147,14 @@ public: * If NULL, the current directory is used. * @param outputStream pointer to output stream that is used when extractResponses is set * to FEM_singleXMLFile. + * @param limitOutput maximum number of responses written to file (0 means unlimited) */ DcmFindSCUDefaultCallback( DcmFindSCUExtractMode extractResponses, int cancelAfterNResponses, const char *outputDirectory = NULL, - STD_NAMESPACE ofstream *outputStream = NULL); + STD_NAMESPACE ofstream *outputStream = NULL, + const unsigned int limitOutput = 0); /// destructor virtual ~DcmFindSCUDefaultCallback() {} @@ -172,10 +174,13 @@ public: private: /// mode specifying whether and how to extract C-FIND responses. - DcmFindSCUExtractMode extractResponses_; + const DcmFindSCUExtractMode extractResponses_; /// if non-negative, a C-FIND-CANCEL will be issued after the given number of incoming C-FIND-RSP messages. - int cancelAfterNResponses_; + const int cancelAfterNResponses_; + + /// maximum number of responses written to file (default: unlimited) + const unsigned int limitOutput_; /// directory used to store the output files (e.g. response datasets). OFString outputDirectory_; @@ -200,6 +205,15 @@ public: /// destructor. Destroys network structure if not done already. virtual ~DcmFindSCU(); + /** set maximum number of responses written to file. + * Limiting the number of responses written to file might be useful e.g. if the + * C-FIND-CANCEL request does not prevent the SCP from sending further C-FIND-RSP + * messages. Also see various "extract" parameters of performQuery() method. + * @param limit maximum number of responses written to file (0 means unlimited) + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition setOutputResponseLimit(const unsigned int limit); + /** initialize the network structure. This should be done only once. * @param acse_timeout timeout for ACSE operations, in seconds * @return EC_Normal if successful, an error code otherwise. @@ -376,6 +390,9 @@ private: /// pointer to network structure T_ASC_Network *net_; + /// maximum number of responses written to file (default: unlimited) + unsigned int outputResponseLimit_; + }; #endif diff --git a/dcmnet/include/dcmtk/dcmnet/dimse.h b/dcmnet/include/dcmtk/dcmnet/dimse.h index e03a63dc..e9da634a 100644 --- a/dcmnet/include/dcmtk/dcmnet/dimse.h +++ b/dcmnet/include/dcmtk/dcmnet/dimse.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -124,53 +124,119 @@ extern DCMTK_DCMNET_EXPORT OFGlobal dcmMaxOutgoingPDUSize; /* default 2^ * General Status Codes. */ #define STATUS_Success 0x0000 -#define STATUS_Pending 0xff00 +#define STATUS_Pending 0xff00 // deprecated, will be removed in a future version -#define DICOM_PENDING_STATUS(status) (((status) & 0xff00) == 0xff00) -#define DICOM_WARNING_STATUS(status) ((((status) & 0xf000) == 0xb000) || ((status) == 0x0107) || ((status) == 0x0116)) +/* + * Status Classes (see DICOM PS3.7 Annex C). + */ +#define DICOM_SUCCESS_STATUS(status) ((status) == 0x0000) +#define DICOM_FAILURE_STATUS(status) ((((status) & 0xf000) == 0xa000) || (((status) & 0xf000) == 0xc000) || ((((status) & 0xff00) == 0x0100) && ((status) != 0x0107) && ((status) != 0x0116)) || (((status) & 0xff00) == 0x0200)) +#define DICOM_WARNING_STATUS(status) ((((status) & 0xf000) == 0xb000) || ((status) == 0x0001) || ((status) == 0x0107) || ((status) == 0x0116)) +#define DICOM_CANCEL_STATUS(status) ((status) == 0xfe00) +#define DICOM_PENDING_STATUS(status) (((status) == 0xff00) || ((status) == 0xff01)) +#define DICOM_STANDARD_STATUS(status) (((status) == 0x0000) || ((status) == 0x0001) || (((status) & 0xff00) == 0x0100) || (((status) & 0xff00) == 0x0200) || (((status) & 0xf000) == 0xa000) || (((status) & 0xf000) == 0xb000) || (((status) & 0xf000) == 0xc000) || ((status) == 0xfe00) || ((status) == 0xff00) || ((status) == 0xff01)) /* * Service Class Specific Status Codes. - * NOTE: some codes are only significant in the high byte - * or high nibble (4 bits). + * NOTE: some codes are only significant in the high byte or high nibble (4 bits). */ -/* Storage Specific Codes*/ -#define STATUS_STORE_Refused_OutOfResources /* high byte */ 0xa700 + +/* General C-ECHO Codes */ +#define STATUS_ECHO_Success 0x0000 +#define STATUS_ECHO_Refused_SOPClassNotSupported 0x0122 +#define STATUS_ECHO_DuplicateInvocation 0x0210 +#define STATUS_ECHO_UnrecognizedOperation 0x0211 +#define STATUS_ECHO_MistypedArgument 0x0212 + +/* General C-STORE Codes */ +#define STATUS_STORE_Success 0x0000 #define STATUS_STORE_Refused_SOPClassNotSupported 0x0122 +#define STATUS_STORE_Refused_NotAuthorized 0x0124 +#define STATUS_STORE_InvalidSOPClass 0x0117 +#define STATUS_STORE_DuplicateInvocation 0x0210 +#define STATUS_STORE_UnrecognizedOperation 0x0211 +#define STATUS_STORE_MistypedArgument 0x0212 +/* Service Class Specific C-STORE Codes (Storage) */ +#define STATUS_STORE_Refused_OutOfResources /* high byte */ 0xa700 #define STATUS_STORE_Error_DataSetDoesNotMatchSOPClass /* high byte */ 0xa900 #define STATUS_STORE_Error_CannotUnderstand /* high nibble */ 0xc000 #define STATUS_STORE_Warning_CoercionOfDataElements 0xb000 #define STATUS_STORE_Warning_DataSetDoesNotMatchSOPClass 0xb007 #define STATUS_STORE_Warning_ElementsDiscarded 0xb006 -/* Find Specific Codes */ -#define STATUS_FIND_Refused_OutOfResources 0xa700 +/* General C-FIND Codes */ +#define STATUS_FIND_Success 0x0000 #define STATUS_FIND_Refused_SOPClassNotSupported 0x0122 -#define STATUS_FIND_Failed_IdentifierDoesNotMatchSOPClass 0xa900 +#define STATUS_FIND_Cancel 0xfe00 +/* Service Class Specific C-FIND Codes */ +/* (Query/Retrieve, Modality Worklist Management, Relevant Patient Information Query) */ +#define STATUS_FIND_Success_MatchingIsComplete 0x0000 +#define STATUS_FIND_Refused_OutOfResources 0xa700 +#define STATUS_FIND_Failed_IdentifierDoesNotMatchSOPClass 0xa900 // deprecated, will be removed in a future version +#define STATUS_FIND_Error_DataSetDoesNotMatchSOPClass 0xa900 #define STATUS_FIND_Failed_UnableToProcess /* high nibble */ 0xc000 +#define STATUS_FIND_Failed_MoreThanOneMatchFound 0xc100 +#define STATUS_FIND_Failed_UnableToSupportRequestedTemplate 0xc200 #define STATUS_FIND_Cancel_MatchingTerminatedDueToCancelRequest 0xfe00 +#define STATUS_FIND_Pending_MatchesAreContinuing 0xff00 #define STATUS_FIND_Pending_WarningUnsupportedOptionalKeys 0xff01 -/* Move Specific Codes */ +/* General C-MOVE Codes */ +#define STATUS_MOVE_Success 0x0000 +#define STATUS_MOVE_Refused_SOPClassNotSupported 0x0122 +#define STATUS_MOVE_Refused_NotAuthorized 0x0124 +#define STATUS_MOVE_Cancel 0xfe00 +#define STATUS_MOVE_DuplicateInvocation 0x0210 +#define STATUS_MOVE_UnrecognizedOperation 0x0211 +#define STATUS_MOVE_MistypedArgument 0x0212 +/* Service Class Specific C-MOVE Codes */ +/* (Query/Retrieve, Composite Instance Root Retrieve) */ +#define STATUS_MOVE_Success_SubOperationsCompleteNoFailures 0x0000 #define STATUS_MOVE_Refused_OutOfResourcesNumberOfMatches 0xa701 #define STATUS_MOVE_Refused_OutOfResourcesSubOperations 0xa702 -#define STATUS_MOVE_Failed_SOPClassNotSupported 0x0122 -#define STATUS_MOVE_Failed_MoveDestinationUnknown 0xa801 -#define STATUS_MOVE_Failed_IdentifierDoesNotMatchSOPClass 0xa900 +#define STATUS_MOVE_Refused_MoveDestinationUnknown 0xa801 +#define STATUS_MOVE_Failed_SOPClassNotSupported 0x0122 // deprecated, will be removed in a future version +#define STATUS_MOVE_Failed_MoveDestinationUnknown 0xa801 // deprecated, will be removed in a future version +#define STATUS_MOVE_Failed_IdentifierDoesNotMatchSOPClass 0xa900 // deprecated, will be removed in a future version +#define STATUS_MOVE_Error_DataSetDoesNotMatchSOPClass 0xa900 +#define STATUS_MOVE_Failed_NoneOfTheFramesWereFoundInSOPInstance 0xaa00 +#define STATUS_MOVE_Failed_UnableToCreateNewObjectForThisSOPClass 0xaa01 +#define STATUS_MOVE_Failed_UnableToExtractFrames 0xaa02 +#define STATUS_MOVE_Failed_TimeBasedRequestForNonTimeBasedSOPInstance 0xaa03 +#define STATUS_MOVE_Failed_InvalidRequest 0xaa04 #define STATUS_MOVE_Failed_UnableToProcess /* high nibble */ 0xc000 #define STATUS_MOVE_Cancel_SubOperationsTerminatedDueToCancelIndication 0xfe00 #define STATUS_MOVE_Warning_SubOperationsCompleteOneOrMoreFailures 0xb000 - -/* Get Specific Codes */ +#define STATUS_MOVE_Pending_SubOperationsAreContinuing 0xff00 + +/* General C-GET Codes */ +#define STATUS_GET_Success 0x0000 +#define STATUS_GET_Refused_SOPClassNotSupported 0x0122 +#define STATUS_GET_Cancel 0xfe00 +#define STATUS_GET_DuplicateInvocation 0x0210 +#define STATUS_GET_UnrecognizedOperation 0x0211 +#define STATUS_GET_MistypedArgument 0x0212 +/* Service Class Specific C-GET Codes */ +/* (Query/Retrieve, Composite Instance Root Retrieve and others) */ +#define STATUS_GET_Success_SubOperationsCompleteNoFailures 0x0000 #define STATUS_GET_Refused_OutOfResourcesNumberOfMatches 0xa701 #define STATUS_GET_Refused_OutOfResourcesSubOperations 0xa702 -#define STATUS_GET_Failed_SOPClassNotSupported 0x0122 -#define STATUS_GET_Failed_IdentifierDoesNotMatchSOPClass 0xa900 +#define STATUS_GET_Failed_SOPClassNotSupported 0x0122 // deprecated, will be removed in a future version +#define STATUS_GET_Failed_IdentifierDoesNotMatchSOPClass 0xa900 // deprecated, will be removed in a future version +#define STATUS_GET_Error_DataSetDoesNotMatchSOPClass 0xa900 +#define STATUS_GET_Failed_NoneOfTheFramesWereFoundInSOPInstance 0xaa00 +#define STATUS_GET_Failed_UnableToCreateNewObjectForThisSOPClass 0xaa01 +#define STATUS_GET_Failed_UnableToExtractFrames 0xaa02 +#define STATUS_GET_Failed_TimeBasedRequestForNonTimeBasedSOPInstance 0xaa03 +#define STATUS_GET_Failed_InvalidRequest 0xaa04 #define STATUS_GET_Failed_UnableToProcess /* high nibble */ 0xc000 #define STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication 0xfe00 #define STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures 0xb000 +#define STATUS_GET_Pending_SubOperationsAreContinuing 0xff00 -/* DIMSE-N Specific Codes */ +/* General DIMSE-N Codes */ +#define STATUS_N_Success 0x0000 +#define STATUS_N_Refused_NotAuthorized 0x0124 #define STATUS_N_Cancel 0xfe00 #define STATUS_N_AttributeListError 0x0107 #define STATUS_N_SOPClassNotSupported 0x0122 @@ -180,32 +246,66 @@ extern DCMTK_DCMNET_EXPORT OFGlobal dcmMaxOutgoingPDUSize; /* default 2^ #define STATUS_N_InvalidArgumentValue 0x0115 #define STATUS_N_InvalidAttributeValue 0x0106 #define STATUS_N_AttributeValueOutOfRange 0x0116 -#define STATUS_N_InvalidObjectInstance 0x0117 +#define STATUS_N_InvalidObjectInstance 0x0117 // deprecated, will be removed in a future version +#define STATUS_N_InvalidSOPInstance 0x0117 #define STATUS_N_MissingAttribute 0x0120 #define STATUS_N_MissingAttributeValue 0x0121 #define STATUS_N_MistypedArgument 0x0212 +#define STATUS_N_NoSuchAction 0x0123 #define STATUS_N_NoSuchArgument 0x0114 #define STATUS_N_NoSuchAttribute 0x0105 #define STATUS_N_NoSuchEventType 0x0113 -#define STATUS_N_NoSuchObjectInstance 0x0112 +#define STATUS_N_NoSuchObjectInstance 0x0112 // deprecated, will be removed in a future version +#define STATUS_N_NoSuchSOPInstance 0x0112 #define STATUS_N_NoSuchSOPClass 0x0118 #define STATUS_N_ProcessingFailure 0x0110 #define STATUS_N_ResourceLimitation 0x0213 #define STATUS_N_UnrecognizedOperation 0x0211 -#define STATUS_N_NoSuchAction 0x0123 +/* the following Codes are used by multiple Services */ +#define STATUS_N_Warning_RequestedOptionalAttributesNotSupported 0x0001 -/* Print Management Service Class Specific Codes */ +/* Service Class Specific DIMSE-N Codes */ +/* (Print Management) */ #define STATUS_N_PRINT_BFS_Warn_MemoryAllocation 0xb600 #define STATUS_N_PRINT_BFS_Warn_NoSessionPrinting 0xb601 #define STATUS_N_PRINT_BFS_Warn_EmptyPage 0xb602 #define STATUS_N_PRINT_BFB_Warn_EmptyPage 0xb603 +#define STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageDemagnified 0xb604 +#define STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageCropped 0xb609 +#define STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageDecimated 0xb60a #define STATUS_N_PRINT_BFS_Fail_NoFilmBox 0xc600 #define STATUS_N_PRINT_BFS_Fail_PrintQueueFull 0xc601 -#define STATUS_N_PRINT_BSB_Fail_PrintQueueFull 0xc602 +#define STATUS_N_PRINT_BFB_Fail_PrintQueueFull 0xc602 #define STATUS_N_PRINT_BFS_BFB_Fail_ImageSize 0xc603 -#define STATUS_N_PRINT_BFS_BFB_Fail_PositionCollision 0xc604 +#define STATUS_N_PRINT_BFS_BFB_Fail_PositionCollision 0xc604 // retired, see DICOM PS3.4 +#define STATUS_N_PRINT_BFS_BFB_Fail_CombinedImageSize 0xc613 +#define STATUS_N_PRINT_IB_Warn_MinMaxDensity 0xb605 #define STATUS_N_PRINT_IB_Fail_InsufficientMemory 0xc605 #define STATUS_N_PRINT_IB_Fail_MoreThanOneVOILUT 0xc606 +/* (Modality Performed Procedure Step Retrieve) */ +#define STATUS_N_MPPS_Warning_RequestedOptionalAttributesNotSupported 0x0001 +/* (Application Event Logging) */ +#define STATUS_N_LOG_Failure_ProceduralLoggingNotAvailable 0xc101 +#define STATUS_N_LOG_Failure_EventInformationDoesNotMatchTemplate 0xc102 +#define STATUS_N_LOG_Failure_CannotMatchEventToCurrentStudy 0xc103 +#define STATUS_N_LOG_Failure_IDsInconsistentInMatchingCurrentStudy 0xc104 +#define STATUS_N_LOG_Warning_SynchronizationFrameOfReferenceDoesNotMatch 0xb101 +#define STATUS_N_LOG_Warning_StudyInstanceUIDCoercion 0xb102 +#define STATUS_N_LOG_Warning_IDsInconsistentInMatchingCurrentStudy 0xb104 +/* (Media Creation Management) */ +#define STATUS_N_MEDIA_Failed_MediaCreationActionAlreadyReceived 0xa510 +#define STATUS_N_MEDIA_Failed_MediaCreationRequestAlreadyCompleted 0xc201 +#define STATUS_N_MEDIA_Failed_MediaCreationRequestAlreadyInProgress 0xc202 +#define STATUS_N_MEDIA_Failed_CancellationDenied 0xc203 +#define STATUS_N_MEDIA_Warning_RequestedOptionalAttributesNotSupported 0x0001 + +// --- TODO (DIMSE-N) --- + +// the following Services use different DIMSE Status Code meanings for +// each SOP Class, including standard Codes such as 0x0000 (Success): + +/* (Unified Procedure Step) */ +/* (RT Machine Verification) */ /* diff --git a/dcmnet/include/dcmtk/dcmnet/diutil.h b/dcmnet/include/dcmtk/dcmnet/diutil.h index dd1eb355..5191f670 100644 --- a/dcmnet/include/dcmtk/dcmnet/diutil.h +++ b/dcmnet/include/dcmtk/dcmnet/diutil.h @@ -139,7 +139,7 @@ DCMTK_DCMNET_EXPORT const char *DU_neventReportStatusString(Uint16 statusCode); /** Logs result of a select() call. According to the select() documentation, * a value of > 1 means that data has arrived. This is logged on TRACE level * since it should be a very regular case. If select() returns 0, a timeout - * has occured, and in case of -1 another error happened (e.g. interrupt). + * has occurred, and in case of -1 another error happened (e.g. interrupt). * These two events are logged to DEBUG log level. * Note that this function makes use of errno (Unix) or WSAGetLastError() * (Windows aka Winsock), so it must be called right after the select() call diff --git a/dcmnet/include/dcmtk/dcmnet/dul.h b/dcmnet/include/dcmtk/dcmnet/dul.h index 9e87d22d..aa808e76 100644 --- a/dcmnet/include/dcmtk/dcmnet/dul.h +++ b/dcmnet/include/dcmtk/dcmnet/dul.h @@ -402,7 +402,7 @@ typedef enum { */ #define DUL_DULCOMPAT 2768240730UL -#define DUL_DIMSECOMPAT 983040UL +#define DUL_DIMSECOMPAT 1048576UL #define DUL_MAXPDUCOMPAT 4278190335UL /* Define the function prototypes for this facility. diff --git a/dcmnet/include/dcmtk/dcmnet/scp.h b/dcmnet/include/dcmtk/dcmnet/scp.h index de7ec187..17c54c1d 100644 --- a/dcmnet/include/dcmtk/dcmnet/scp.h +++ b/dcmnet/include/dcmtk/dcmnet/scp.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2009-2018, OFFIS e.V. + * Copyright (C) 2009-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -23,15 +23,14 @@ #ifndef SCP_H #define SCP_H -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/oflog/oflog.h" -#include "dcmtk/dcmdata/dctk.h" /* Covers most common dcmdata classes */ +#include "dcmtk/dcmdata/dctk.h" /* Covers most common dcmdata classes */ #include "dcmtk/dcmnet/assoc.h" -#include "dcmtk/dcmnet/dimse.h" /* DIMSE network layer */ +#include "dcmtk/dcmnet/dimse.h" /* DIMSE network layer */ +#include "dcmtk/dcmnet/diutil.h" /* for DCMNET_WARN() */ #include "dcmtk/dcmnet/scpcfg.h" -#include "dcmtk/dcmnet/diutil.h" /* for DCMNET_WARN() */ - +#include "dcmtk/oflog/oflog.h" // include this file in doxygen documentation @@ -39,23 +38,22 @@ * @brief general Service Class Provider (SCP) class */ - /** Structure representing single process in multi-process mode */ struct DCMTK_DCMNET_EXPORT DcmProcessSlotType { - /// Name of peer - DIC_NODENAME peerName; - /// Calling AE title - DIC_AE callingAETitle; - /// Called AE title - DIC_AE calledAETitle; - /// Process ID - int processId; - /// Start time - time_t startTime; - /// Indicator if process has storage ability - OFBool hasStorageAbility; + /// Name of peer + DIC_NODENAME peerName; + /// Calling AE title + DIC_AE callingAETitle; + /// Called AE title + DIC_AE calledAETitle; + /// Process ID + int processId; + /// Start time + time_t startTime; + /// Indicator if process has storage ability + OFBool hasStorageAbility; }; /** Action codes that can be given to DcmSCP to control behavior during SCP's operation. @@ -63,36 +61,36 @@ struct DCMTK_DCMNET_EXPORT DcmProcessSlotType */ enum DcmSCPActionType { - /// No action defined - DCMSCP_ACTION_UNDEFINED, - /// Tell SCP to refuse association - DCMSCP_ACTION_REFUSE_ASSOCIATION + /// No action defined + DCMSCP_ACTION_UNDEFINED, + /// Tell SCP to refuse association + DCMSCP_ACTION_REFUSE_ASSOCIATION }; /** Codes denoting a reason for refusing an association */ enum DcmRefuseReasonType { - /// Too many associations (SCP cannot handle a further association) - DCMSCP_TOO_MANY_ASSOCIATIONS, - /// Forking a new SCP process failed - DCMSCP_CANNOT_FORK, - /// Refusing association because of bad application context name - DCMSCP_BAD_APPLICATION_CONTEXT_NAME, - /// Refusing association because of disallowed connecting host - DCMSCP_CALLING_HOST_NOT_ALLOWED, - /// Refusing association because of unaccepted called AE title - DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED, - /// Refusing association because of unaccepted calling AE title - DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED, - /// Refusing association because SCP was forced to do so - DCMSCP_FORCED, - /// Refusing association because of missing Implementation Class UID - DCMSCP_NO_IMPLEMENTATION_CLASS_UID, - /// Refusing association because of no acceptable Presentation Contexts - DCMSCP_NO_PRESENTATION_CONTEXTS, - /// Refusing association because of internal error - DCMSCP_INTERNAL_ERROR + /// Too many associations (SCP cannot handle a further association) + DCMSCP_TOO_MANY_ASSOCIATIONS, + /// Forking a new SCP process failed + DCMSCP_CANNOT_FORK, + /// Refusing association because of bad application context name + DCMSCP_BAD_APPLICATION_CONTEXT_NAME, + /// Refusing association because of disallowed connecting host + DCMSCP_CALLING_HOST_NOT_ALLOWED, + /// Refusing association because of unaccepted called AE title + DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED, + /// Refusing association because of unaccepted calling AE title + DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED, + /// Refusing association because SCP was forced to do so + DCMSCP_FORCED, + /// Refusing association because of missing Implementation Class UID + DCMSCP_NO_IMPLEMENTATION_CLASS_UID, + /// Refusing association because of no acceptable Presentation Contexts + DCMSCP_NO_PRESENTATION_CONTEXTS, + /// Refusing association because of internal error + DCMSCP_INTERNAL_ERROR }; /** Structure representing a single Presentation Context. Fields "reserved" and "result" @@ -101,29 +99,28 @@ enum DcmRefuseReasonType */ struct DCMTK_DCMNET_EXPORT DcmPresentationContextInfo { - DcmPresentationContextInfo() - : presentationContextID(0) - , abstractSyntax() - , proposedSCRole(0) - , acceptedSCRole(0) - , acceptedTransferSyntax() - { - } - - /// Presentation Context ID as proposed by SCU - Uint8 presentationContextID; - /// Abstract Syntax name (UID) as proposed by SCU - OFString abstractSyntax; - /// SCP role as proposed from SCU - Uint8 proposedSCRole; - /// Role accepted by SCP for this Presentation Context - Uint8 acceptedSCRole; - /// Transfer Syntax accepted for this Presentation Context (UID) - OFString acceptedTransferSyntax; - // Fields "reserved" and "result" not included from DUL_PRESENTATIONCONTEXT + DcmPresentationContextInfo() + : presentationContextID(0) + , abstractSyntax() + , proposedSCRole(0) + , acceptedSCRole(0) + , acceptedTransferSyntax() + { + } + + /// Presentation Context ID as proposed by SCU + Uint8 presentationContextID; + /// Abstract Syntax name (UID) as proposed by SCU + OFString abstractSyntax; + /// SCP role as proposed from SCU + Uint8 proposedSCRole; + /// Role accepted by SCP for this Presentation Context + Uint8 acceptedSCRole; + /// Transfer Syntax accepted for this Presentation Context (UID) + OFString acceptedTransferSyntax; + // Fields "reserved" and "result" not included from DUL_PRESENTATIONCONTEXT }; - /** Base class for implementing a DICOM Service Class Provider (SCP). Derived classes can * add the presentation contexts they want to support, set further parameters (port, peer * host name, etc. as desired) and then call DcmSCP's listen() method to start the server. @@ -141,1022 +138,1029 @@ class DCMTK_DCMNET_EXPORT DcmSCP { public: - - /** Constructor. Initializes internal member variables. - */ - DcmSCP(); - - /** Virtual destructor, frees internal memory. - */ - virtual ~DcmSCP(); - - /** Starts providing the implemented services to SCUs. - * After calling this method the SCP is listening for connection requests. - * @return The result. Per default, the method only returns in case of fatal errors. - * However, there are ways to stop listening in a controlled way: - *
    - *
  • In non-blocking mode, use stopAfterConnectionTimeout() in order - * shut down after the TCP timeout set with setConnectionTimeout() has - * occurred. In that case, the method returns with NET_EC_StopAfterConnectionTimeout.
  • - *
  • In non-blocking and blocking mode, stopAfterCurrentAssociation() can - * be used to return after an association has been handled and ended. - * In that case, NET_EC_StopAfterAssociation is returned.
  • - *
- * Other error codes include - *
    - *
  • NET_EC_InvalidSCPAssociationProfile: Returned if the SCP's presentation - * context information is invalid (e.g. no presentation contexts have - * been added). - *
  • - *
  • NET_EC_InsufficientPortPrivileges: Returned if the SCP is not - * allowed to open the specified TCP port for listening. The reason - * may be that you try to open a port number below 1024 on a Unix-like - * system as non-root user. - *
  • EC_setuidFailed: Returned (on Unix-like systems) if the DcmSCP - * was not able to drop root privileges. - *
- */ - virtual OFCondition listen(); - - /* ************************************************************* */ - /* Set methods for configuring SCP behavior */ - /* ************************************************************* */ - - /** Enables negotiation of the Verification SOP Class. It adds the Verification - * SOP Class to the list of supported abstract syntaxes for the given profile. - * All uncompressed transfer syntaxes are supported. If Verification SOP - * class is added here, DcmSCP will respond to related C-ECHO requests. Note - * that this cannot be reverted. - * The default behavior of DcmSCP is not to support any SOP Class at all. - * @param profile [in] The profile Verification SOP Class should - * be added to. The default is to add it to the - * DcmSCP's internal standard profile called - * "DEFAULT". - * @return EC_Normal if Verification SOP Class could be added, - * error otherwise. - */ - OFCondition setEnableVerification(const OFString& profile="DEFAULT"); - - /** Add abstract syntax to presentation contexts the SCP is able to negotiate with SCUs. - * @param abstractSyntax [in] The UID of the abstract syntax (e.g.\ SOP class) to add - * @param xferSyntaxes [in] List of transfer syntaxes (UIDs) that should be supported - * for the given abstract syntax name - * @param requestorRole [in] The role to be negotiated. This denotes the role of the - * the association requestor that this instance should accept, i.e. if - * set to ASC_SC_ROLE_SCP it means that the association requestor - * is allowed to negotiate the SCP role, thus, that this DcmSCP instance - * will be playing the SCU role for this abstract syntax. The default - * role (ASC_SC_ROLE_DEFAULT) implicates that this DcmSCP instance - * will be allowed to play the SCP role only, i.e. it will acknowledge - * such an explicit SCU role request, but also it will accept a proposal - * for the abstract syntax with no explicit role being proposed - * at all (since per default the requestor is SCU and the acceptor SCP). - * @param profile [in] The profile the abstract syntax should be added to. The - * default is to add it to the DcmSCP's internal standard - * profile called "DEFAULT". - * @return EC_Normal if adding was successful, an error code otherwise - */ - virtual OFCondition addPresentationContext(const OFString &abstractSyntax, - const OFList &xferSyntaxes, - const T_ASC_SC_ROLE requestorRole = ASC_SC_ROLE_DEFAULT, - const OFString &profile = "DEFAULT"); - - /** Set SCP's TCP/IP listening port - * @param port [in] The port number to listen on. Note that usually on Unix-like systems - * only root user is permitted to open ports below 1024. - */ - void setPort(const Uint16 port); - - /** Set AE title of the server - * @param aetitle [in] The AE title of the server. By default, all SCU association requests - * calling another AE title will be rejected. This behavior can be - * changed by using the setRespondWithCalledAETitle() method. - */ - void setAETitle(const OFString &aetitle); - - /** Set SCP to use the called AE title from the SCU request for the response, i.e.\ the SCP - * will always respond with setting it's own name to the one the SCU used for calling. - * Overrides any AE title eventually set with setAETitle(). - * @param useCalled [in] If OFTrue, the SCP will use the called AE title from the request - * for responding. DcmSCP's default is OFFalse. - */ - void setRespondWithCalledAETitle(const OFBool useCalled); - - /** Loads association configuration file - * @param assocFile [in] The filename of the association configuration to be loaded. The - * association configuration file must be valid for an SCP. - * @return EC_Normal if loading was successful, error otherwise - */ - virtual OFCondition loadAssociationCfgFile(const OFString &assocFile); - - /** If an association profile should be selected, either by loading an association - * configuration file or using the addPresentationContext() function, one of those can - * be selected and checked for validity using this method. - * @param profileName [in] The name of the association profile which must be configured - * before being selected here - * @return EC_Normal if selecting/checking was successful, an error code otherwise - */ - virtual OFCondition setAndCheckAssociationProfile(const OFString &profileName); - - /** Force every association request to be refused by SCP, no matter what the SCU is - * offering - * @param doRefuse [in] If OFTrue, every association is being refused. DcmSCP's default - * is not to refuse every association. - */ - void forceAssociationRefuse(const OFBool doRefuse); - - /** Set maximum PDU size the SCP is able to receive. This size is sent in association - * response message to SCU. - * @param maxRecPDU [in] The maximum PDU size to use in bytes - */ - void setMaxReceivePDULength(const Uint32 maxRecPDU); - - /** Set whether waiting for a TCP/IP connection should be blocking or non-blocking. - * In non-blocking mode, the networking routines will wait for specified connection - * timeout, see setConnectionTimeout() function. In blocking mode, no timeout is set - * but the operating system's network routines will be used to read from the socket - * for incoming data. In the worst case, this may be a long time until that call - * returns. The default of DcmSCP is blocking mode. - * @param blockingMode [in] Either DUL_BLOCK for blocking mode or DUL_NOBLOCK - * for non-blocking mode - */ - void setConnectionBlockingMode(const DUL_BLOCKOPTIONS blockingMode); - - /** Set whether DIMSE messaging should be blocking or non-blocking. In non-blocking mode, - * the networking routines will wait for DIMSE messages for the specified DIMSE timeout - * time, see setDIMSETimeout() function. In blocking mode, no timeout is set but the - * operating system's network routines will be used to read from the socket for new data. - * In the worst case, this may be a long time until that call returns. The default of - * DcmSCP is blocking mode. - * @param blockingMode [in] Either DIMSE_BLOCKING for blocking mode or DIMSE_NONBLOCKING - * for non-blocking mode - */ - void setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode); - - /** Set the timeout to be waited for incoming DIMSE message packets. This is only relevant - * for DIMSE blocking mode messaging (see also setDIMSEBlockingMode()). - * @param dimseTimeout [in] DIMSE receive timeout in seconds - */ - void setDIMSETimeout(const Uint32 dimseTimeout); - - /** Set the timeout used during ACSE messaging protocol. - * @param acseTimeout [in] ACSE timeout in seconds. - */ - void setACSETimeout(const Uint32 acseTimeout); - - /** Set the timeout that should be waited for connection requests. - * Only relevant in non-blocking mode (default). - * @param timeout [in] TCP/IP connection timeout in seconds. - */ - void setConnectionTimeout(const Uint32 timeout); - - /** Set whether to show presentation contexts in verbose or debug mode - * @param mode [in] Show presentation contexts in verbose mode if OFTrue. By default, the - * presentation contexts are shown in debug mode. - */ - void setVerbosePCMode(const OFBool mode); - - /** Enables or disables looking up the host name from a connecting system. - * Note that this sets a GLOBAL flag in DCMTK, i.e. the behavior changes - * for all servers. This should be changed in the future. - * @param mode [in] OFTrue, if host name lookup should be enabled, OFFalse for disabling it. - */ - void setHostLookupEnabled(const OFBool mode); - - /** Set the mode that specifies whether the progress of sending and receiving DIMSE messages - * is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), respectively. - * The progress notification is enabled by default. - * @param mode [in] Disable progress notification if OFFalse - */ - void setProgressNotificationMode(const OFBool mode); - - /** Option to always accept a default role as association acceptor. - * If OFFalse (default) the acceptor will reject a presentation context proposed - * with Default role (no role selection at all) when it is configured for role - * SCP only. If this option is set to OFTrue then such presentation contexts will - * be accepted in Default role (i.e. acceptor does not return role selection for - * this presentation context at all). Overall, if set to OFTrue, there are no - * requestor proposals possible that lead to a complete rejection of a presentation - * context. See also role documentation in dul.h. - * @param enabled If OFTrue, do not reject Default role proposals when configured - * for SCP role. OFFalse (default behaviour): Reject such proposals. - */ - void setAlwaysAcceptDefaultRole(const OFBool enabled); - - /* Get methods for SCP settings */ - - /** Returns TCP/IP port number SCP listens for new connection requests - * @return The port number - */ - Uint16 getPort() const; - - /** Returns SCP's own AE title. Only used if the SCP is not configured to respond with the - * called AE title the SCU uses for association negotiation, see setRespondWithCalledAETitle(). - * @return The configured AE title - */ - const OFString &getAETitle() const; - - /** Returns whether SCP uses the called AE title from SCU requests to respond to connection - * requests instead of a configured AE title - * @return OFTrue, if the SCU's calling AE title is utilized, OFFalse otherwise - */ - OFBool getRespondWithCalledAETitle() const; - - /** Returns whether SCP should refuse any association request no matter what the SCU proposes - * @return OFTrue, if SCP is configured to refuse every association - */ - OFBool getRefuseAssociation() const; - - /** Returns maximum PDU length configured to be received by SCP - * @return Maximum PDU length in bytes - */ - Uint32 getMaxReceivePDULength() const; - - /** Returns whether receiving of TCP/IP connection requests is done in blocking or - * unblocking mode - * @return DUL_BLOCK if in blocking mode, otherwise DUL_NOBLOCK - */ - DUL_BLOCKOPTIONS getConnectionBlockingMode() const; - - /** Returns whether receiving of DIMSE messages is done in blocking or unblocking mode - * @return DIMSE_BLOCKING if in blocking mode, otherwise DIMSE_NONBLOCKING - */ - T_DIMSE_BlockingMode getDIMSEBlockingMode() const; - - /** Returns DIMSE timeout (only applicable in blocking mode) - * @return DIMSE timeout in seconds - */ - Uint32 getDIMSETimeout() const; - - /** Returns ACSE timeout - * @return ACSE timeout in seconds - */ - Uint32 getACSETimeout() const; - - /** Returns connection timeout - * @return TCP/IP connection timeout in seconds - */ - Uint32 getConnectionTimeout() const; - - /** Returns the verbose presentation context mode configured specifying whether details on - * the presentation contexts (negotiated during association setup) should be shown in - * verbose or debug mode. The latter is the default. - * @return The verbose presentation context mode configured - */ - OFBool getVerbosePCMode() const; - - /** Returns whether a connecting system's host name is looked up. - * @return OFTrue, if host name lookup is enabled, OFFalse otherwise - */ - OFBool getHostLookupEnabled() const; - - /** Returns the mode that specifies whether the progress of sending and receiving DIMSE - * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), - * respectively. The progress notification is enabled by default. - * @return The current progress notification mode, enabled if OFTrue - */ - OFBool getProgressNotificationMode() const; - - /** Get access to the configuration of the SCP. Note that the functionality - * on the configuration object is shadowed by other API functions of DcmSCP. - * The existing functions are provided in order to not break users of this - * "older" API where no configuration object existed. - * @return a reference to the DcmSCPConfig object used by this DcmSCP object. - */ - virtual DcmSCPConfig& getConfig(); - - /** Set the DcmSCPConfig object to use for configuring this DcmSCP object. - * A deep copy is performed. - * @param config The configuration to use. - * @return EC_Normal if configuration can be used. The configuration can - * only be changed if the SCP is not yet connected, otherwise - * NET_EC_AlreadyConnected is returned. - * - */ - virtual OFCondition setConfig(const DcmSCPConfig& config); - - /* ************************************************************* */ - /* Methods for receiving runtime (i.e. connection time) infos */ - /* ************************************************************* */ - - /** Returns whether SCP is currently connected. If in multi-process mode, the "father" - * process should always return false here, because connection is always handled by child - * process. - * @return OFTrue, if SCP is currently connected to calling SCU - */ - OFBool isConnected() const; - - /** Returns number of associations currently running. Only applicable in Unix-like - * operating systems. Can only be greater than one when running in multi-process mode. - * @return Number of currently running associations - */ - Uint16 numAssociations() const; - - /** Returns AE title the SCU used as called AE title in association request - * @return AE title the SCP was called with. Empty string if SCP is currently not - * connected. - */ - OFString getCalledAETitle() const; - - /** Returns AE title (calling AE title) the SCU used for association request - * @return Calling AE title of SCU. Empty string if SCP is currently not connected. - */ - OFString getPeerAETitle() const; - - /** Returns IP address of connected SCU - * @return IP address of connected SCU. Empty string if SCP is currently not connected. - */ - OFString getPeerIP() const; - - /** Returns maximum PDU size the communication peer (i.e.\ the SCU) is able to receive - * @return Maximum PDU size the SCU is able to receive. Returns zero if SCP is currently - * not connected. - */ - Uint32 getPeerMaxPDULength() const; - - /// DcmThreadSCP needs access to configuration (m_cfg), at least - friend class DcmThreadSCP; + /** Constructor. Initializes internal member variables. + */ + DcmSCP(); + + /** Virtual destructor, frees internal memory. + */ + virtual ~DcmSCP(); + + /** Starts providing the implemented services to SCUs. + * After calling this method the SCP is listening for connection requests. + * @return The result. Per default, the method only returns in case of fatal errors. + * However, there are ways to stop listening in a controlled way: + *
    + *
  • In non-blocking mode, use stopAfterConnectionTimeout() in order + * shut down after the TCP timeout set with setConnectionTimeout() has + * occurred. In that case, the method returns with NET_EC_StopAfterConnectionTimeout.
  • + *
  • In non-blocking and blocking mode, stopAfterCurrentAssociation() can + * be used to return after an association has been handled and ended. + * In that case, NET_EC_StopAfterAssociation is returned.
  • + *
+ * Other error codes include + *
    + *
  • NET_EC_InvalidSCPAssociationProfile: Returned if the SCP's presentation + * context information is invalid (e.g. no presentation contexts have + * been added). + *
  • + *
  • NET_EC_InsufficientPortPrivileges: Returned if the SCP is not + * allowed to open the specified TCP port for listening. The reason + * may be that you try to open a port number below 1024 on a Unix-like + * system as non-root user. + *
  • EC_setuidFailed: Returned (on Unix-like systems) if the DcmSCP + * was not able to drop root privileges. + *
+ */ + virtual OFCondition listen(); + + /** Alternative interface to providing the implemented services to SCUs. + * This method opens the TCP port for incoming connections, drops root privileges + * if necessary and then returns. The caller can then perform short other operations + * and finally call acceptAssociations(). If any SCU tries to connect between + * this method and the call to acceptAssociations(), they are placed on the + * TCP listen backlog and will be handled by acceptAssociations() unless they + * time out or the backlog overflows (the size of the backlog is defined by the + * PRV_LISTENBACKLOG macro). + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition openListenPort(); + + /** Alternative interface to providing the implemented services to SCUs. + * This method should be called after a call to openListenPort(). + * @return The result. Per default, the method only returns in case of fatal errors. + * See documentation of listen() method on how to stop listening in a controlled way. + */ + virtual OFCondition acceptAssociations(); + + /* ************************************************************* */ + /* Set methods for configuring SCP behavior */ + /* ************************************************************* */ + + /** Enables negotiation of the Verification SOP Class. It adds the Verification + * SOP Class to the list of supported abstract syntaxes for the given profile. + * All uncompressed transfer syntaxes are supported. If Verification SOP + * class is added here, DcmSCP will respond to related C-ECHO requests. Note + * that this cannot be reverted. + * The default behavior of DcmSCP is not to support any SOP Class at all. + * @param profile [in] The profile Verification SOP Class should + * be added to. The default is to add it to the + * DcmSCP's internal standard profile called + * "DEFAULT". + * @return EC_Normal if Verification SOP Class could be added, + * error otherwise. + */ + OFCondition setEnableVerification(const OFString& profile = "DEFAULT"); + + /** Add abstract syntax to presentation contexts the SCP is able to negotiate with SCUs. + * @param abstractSyntax [in] The UID of the abstract syntax (e.g.\ SOP class) to add + * @param xferSyntaxes [in] List of transfer syntaxes (UIDs) that should be supported + * for the given abstract syntax name + * @param requestorRole [in] The role to be negotiated. This denotes the role of the + * the association requestor that this instance should accept, i.e. if + * set to ASC_SC_ROLE_SCP it means that the association requestor + * is allowed to negotiate the SCP role, thus, that this DcmSCP instance + * will be playing the SCU role for this abstract syntax. The default + * role (ASC_SC_ROLE_DEFAULT) implicates that this DcmSCP instance + * will be allowed to play the SCP role only, i.e. it will acknowledge + * such an explicit SCU role request, but also it will accept a proposal + * for the abstract syntax with no explicit role being proposed + * at all (since per default the requestor is SCU and the acceptor SCP). + * @param profile [in] The profile the abstract syntax should be added to. The + * default is to add it to the DcmSCP's internal standard + * profile called "DEFAULT". + * @return EC_Normal if adding was successful, an error code otherwise + */ + virtual OFCondition addPresentationContext(const OFString& abstractSyntax, + const OFList& xferSyntaxes, + const T_ASC_SC_ROLE requestorRole = ASC_SC_ROLE_DEFAULT, + const OFString& profile = "DEFAULT"); + + /** Set SCP's TCP/IP listening port + * @param port [in] The port number to listen on. Note that usually on Unix-like systems + * only root user is permitted to open ports below 1024. + */ + void setPort(const Uint16 port); + + /** Set AE title of the server + * @param aetitle [in] The AE title of the server. By default, all SCU association requests + * calling another AE title will be rejected. This behavior can be + * changed by using the setRespondWithCalledAETitle() method. + */ + void setAETitle(const OFString& aetitle); + + /** Set SCP to use the called AE title from the SCU request for the response, i.e.\ the SCP + * will always respond with setting it's own name to the one the SCU used for calling. + * Overrides any AE title eventually set with setAETitle(). + * @param useCalled [in] If OFTrue, the SCP will use the called AE title from the request + * for responding. DcmSCP's default is OFFalse. + */ + void setRespondWithCalledAETitle(const OFBool useCalled); + + /** Loads association configuration file + * @param assocFile [in] The filename of the association configuration to be loaded. The + * association configuration file must be valid for an SCP. + * @return EC_Normal if loading was successful, error otherwise + */ + virtual OFCondition loadAssociationCfgFile(const OFString& assocFile); + + /** If an association profile should be selected, either by loading an association + * configuration file or using the addPresentationContext() function, one of those can + * be selected and checked for validity using this method. + * @param profileName [in] The name of the association profile which must be configured + * before being selected here + * @return EC_Normal if selecting/checking was successful, an error code otherwise + */ + virtual OFCondition setAndCheckAssociationProfile(const OFString& profileName); + + /** Force every association request to be refused by SCP, no matter what the SCU is + * offering + * @param doRefuse [in] If OFTrue, every association is being refused. DcmSCP's default + * is not to refuse every association. + */ + void forceAssociationRefuse(const OFBool doRefuse); + + /** Set maximum PDU size the SCP is able to receive. This size is sent in association + * response message to SCU. + * @param maxRecPDU [in] The maximum PDU size to use in bytes + */ + void setMaxReceivePDULength(const Uint32 maxRecPDU); + + /** Set whether waiting for a TCP/IP connection should be blocking or non-blocking. + * In non-blocking mode, the networking routines will wait for specified connection + * timeout, see setConnectionTimeout() function. In blocking mode, no timeout is set + * but the operating system's network routines will be used to read from the socket + * for incoming data. In the worst case, this may be a long time until that call + * returns. The default of DcmSCP is blocking mode. + * @param blockingMode [in] Either DUL_BLOCK for blocking mode or DUL_NOBLOCK + * for non-blocking mode + */ + void setConnectionBlockingMode(const DUL_BLOCKOPTIONS blockingMode); + + /** Set whether DIMSE messaging should be blocking or non-blocking. In non-blocking mode, + * the networking routines will wait for DIMSE messages for the specified DIMSE timeout + * time, see setDIMSETimeout() function. In blocking mode, no timeout is set but the + * operating system's network routines will be used to read from the socket for new data. + * In the worst case, this may be a long time until that call returns. The default of + * DcmSCP is blocking mode. + * @param blockingMode [in] Either DIMSE_BLOCKING for blocking mode or DIMSE_NONBLOCKING + * for non-blocking mode + */ + void setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode); + + /** Set the timeout to be waited for incoming DIMSE message packets. This is only relevant + * for DIMSE blocking mode messaging (see also setDIMSEBlockingMode()). + * @param dimseTimeout [in] DIMSE receive timeout in seconds + */ + void setDIMSETimeout(const Uint32 dimseTimeout); + + /** Set the timeout used during ACSE messaging protocol. + * @param acseTimeout [in] ACSE timeout in seconds. + */ + void setACSETimeout(const Uint32 acseTimeout); + + /** Set the timeout that should be waited for connection requests. + * Only relevant in non-blocking mode (default). + * @param timeout [in] TCP/IP connection timeout in seconds. + */ + void setConnectionTimeout(const Uint32 timeout); + + /** Set whether to show presentation contexts in verbose or debug mode + * @param mode [in] Show presentation contexts in verbose mode if OFTrue. By default, the + * presentation contexts are shown in debug mode. + */ + void setVerbosePCMode(const OFBool mode); + + /** Enables or disables looking up the host name from a connecting system. + * Note that this sets a GLOBAL flag in DCMTK, i.e. the behavior changes + * for all servers. This should be changed in the future. + * @param mode [in] OFTrue, if host name lookup should be enabled, OFFalse for disabling it. + */ + void setHostLookupEnabled(const OFBool mode); + + /** Set the mode that specifies whether the progress of sending and receiving DIMSE messages + * is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), respectively. + * The progress notification is enabled by default. + * @param mode [in] Disable progress notification if OFFalse + */ + void setProgressNotificationMode(const OFBool mode); + + /** Option to always accept a default role as association acceptor. + * If OFFalse (default) the acceptor will reject a presentation context proposed + * with Default role (no role selection at all) when it is configured for role + * SCP only. If this option is set to OFTrue then such presentation contexts will + * be accepted in Default role (i.e. acceptor does not return role selection for + * this presentation context at all). Overall, if set to OFTrue, there are no + * requestor proposals possible that lead to a complete rejection of a presentation + * context. See also role documentation in dul.h. + * @param enabled If OFTrue, do not reject Default role proposals when configured + * for SCP role. OFFalse (default behaviour): Reject such proposals. + */ + void setAlwaysAcceptDefaultRole(const OFBool enabled); + + /* Get methods for SCP settings */ + + /** Returns TCP/IP port number SCP listens for new connection requests + * @return The port number + */ + Uint16 getPort() const; + + /** Returns SCP's own AE title. Only used if the SCP is not configured to respond with the + * called AE title the SCU uses for association negotiation, see setRespondWithCalledAETitle(). + * @return The configured AE title + */ + const OFString& getAETitle() const; + + /** Returns whether SCP uses the called AE title from SCU requests to respond to connection + * requests instead of a configured AE title + * @return OFTrue, if the SCU's calling AE title is utilized, OFFalse otherwise + */ + OFBool getRespondWithCalledAETitle() const; + + /** Returns whether SCP should refuse any association request no matter what the SCU proposes + * @return OFTrue, if SCP is configured to refuse every association + */ + OFBool getRefuseAssociation() const; + + /** Returns maximum PDU length configured to be received by SCP + * @return Maximum PDU length in bytes + */ + Uint32 getMaxReceivePDULength() const; + + /** Returns whether receiving of TCP/IP connection requests is done in blocking or + * unblocking mode + * @return DUL_BLOCK if in blocking mode, otherwise DUL_NOBLOCK + */ + DUL_BLOCKOPTIONS getConnectionBlockingMode() const; + + /** Returns whether receiving of DIMSE messages is done in blocking or unblocking mode + * @return DIMSE_BLOCKING if in blocking mode, otherwise DIMSE_NONBLOCKING + */ + T_DIMSE_BlockingMode getDIMSEBlockingMode() const; + + /** Returns DIMSE timeout (only applicable in blocking mode) + * @return DIMSE timeout in seconds + */ + Uint32 getDIMSETimeout() const; + + /** Returns ACSE timeout + * @return ACSE timeout in seconds + */ + Uint32 getACSETimeout() const; + + /** Returns connection timeout + * @return TCP/IP connection timeout in seconds + */ + Uint32 getConnectionTimeout() const; + + /** Returns the verbose presentation context mode configured specifying whether details on + * the presentation contexts (negotiated during association setup) should be shown in + * verbose or debug mode. The latter is the default. + * @return The verbose presentation context mode configured + */ + OFBool getVerbosePCMode() const; + + /** Returns whether a connecting system's host name is looked up. + * @return OFTrue, if host name lookup is enabled, OFFalse otherwise + */ + OFBool getHostLookupEnabled() const; + + /** Returns the mode that specifies whether the progress of sending and receiving DIMSE + * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), + * respectively. The progress notification is enabled by default. + * @return The current progress notification mode, enabled if OFTrue + */ + OFBool getProgressNotificationMode() const; + + /** Get access to the configuration of the SCP. Note that the functionality + * on the configuration object is shadowed by other API functions of DcmSCP. + * The existing functions are provided in order to not break users of this + * "older" API where no configuration object existed. + * @return a reference to the DcmSCPConfig object used by this DcmSCP object. + */ + virtual DcmSCPConfig& getConfig(); + + /** Set the DcmSCPConfig object to use for configuring this DcmSCP object. + * A deep copy is performed. + * @param config The configuration to use. + * @return EC_Normal if configuration can be used. The configuration can + * only be changed if the SCP is not yet connected, otherwise + * NET_EC_AlreadyConnected is returned. + * + */ + virtual OFCondition setConfig(const DcmSCPConfig& config); + + /* ************************************************************* */ + /* Methods for receiving runtime (i.e. connection time) infos */ + /* ************************************************************* */ + + /** Returns whether SCP is currently connected. If in multi-process mode, the "father" + * process should always return false here, because connection is always handled by child + * process. + * @return OFTrue, if SCP is currently connected to calling SCU + */ + OFBool isConnected() const; + + /** Returns number of associations currently running. Only applicable in Unix-like + * operating systems. Can only be greater than one when running in multi-process mode. + * @return Number of currently running associations + */ + Uint16 numAssociations() const; + + /** Returns AE title the SCU used as called AE title in association request + * @return AE title the SCP was called with. Empty string if SCP is currently not + * connected. + */ + OFString getCalledAETitle() const; + + /** Returns AE title (calling AE title) the SCU used for association request + * @return Calling AE title of SCU. Empty string if SCP is currently not connected. + */ + OFString getPeerAETitle() const; + + /** Returns IP address of connected SCU + * @return IP address of connected SCU. Empty string if SCP is currently not connected. + */ + OFString getPeerIP() const; + + /** Returns maximum PDU size the communication peer (i.e.\ the SCU) is able to receive + * @return Maximum PDU size the SCU is able to receive. Returns zero if SCP is currently + * not connected. + */ + Uint32 getPeerMaxPDULength() const; + + /// DcmThreadSCP needs access to configuration (m_cfg), at least + friend class DcmThreadSCP; protected: - - /* ********************************************* */ - /* Functions available to derived classes only */ - /* ********************************************* */ - - /** This call returns the presentation context belonging to the given - * presentation context ID. - * @param presID [in] The presentation context ID to look for - * @param abstractSyntax [out] The abstract syntax (UID) for that ID. - * Empty, if such a presentation context does not exist. - * @param transferSyntax [out] The transfer syntax (UID) for that ID. - * Empty, if such a presentation context does not exist. - */ - void findPresentationContext(const T_ASC_PresentationContextID presID, - OFString &abstractSyntax, - OFString &transferSyntax); - - /** Aborts the current association by sending an A-ABORT request to the SCU. - * This method allows derived classes to abort an association in case of severe errors. - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition abortAssociation(); - - /* *********************************************************************** */ - /* Functions particularly interesting for overwriting in derived classes */ - /* *********************************************************************** */ - - /** Handle incoming command set and react accordingly, e.g.\ sending response via - * DIMSE_sendXXXResponse(). The standard handler only knows how to handle - * a C-ECHO request message (by calling handleEchoRequest()) if it is sent on a - * presentation context configured for the Verification SOP Class. - * This function is most likely to be implemented by a derived class - * implementing a specific SCP behavior. - * @param incomingMsg The DIMSE message received - * @param presInfo Additional information on the Presentation Context used - * @return EC_Normal if the message could be handled, error if not. Especially - * DIMSE_BADCOMMANDTYPE should be returned if there is no handler for - * this particular type of DIMSE message. E.g. the default handler in - * DcmSCP only handles C-ECHO requests and, therefore, returns - * DIMSE_BADCOMMANDTYPE otherwise. - */ - virtual OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg, - const DcmPresentationContextInfo &presInfo); - - /** Overwrite this function to be notified about an incoming association request. - * The standard handler only outputs some information to the logger. - * @param params The association parameters that were received. - * @param desiredAction The desired action how to handle this association request. - */ - virtual void notifyAssociationRequest(const T_ASC_Parameters ¶ms, - DcmSCPActionType &desiredAction); - - /** Overwrite this function if called AE title should undergo checking. If - * OFTrue is returned, the AE title is accepted and processing is continued. - * In case of OFFalse, the SCP will refuse the incoming association with - * error "Called Application Entity Title Not Recognized". - * The standard handler always returns OFTrue. - * @param calledAE The called AE title the SCU used that should be checked - * @return OFTrue, if AE title is accepted, OFFalse otherwise - */ - virtual OFBool checkCalledAETitleAccepted(const OFString& calledAE); - - /** Overwrite this function if calling AE title should undergo checking. If - * OFTrue is returned, the AE title is accepted and processing is continued. - * In case of OFFalse, the SCP will refuse the incoming association with - * error "Calling Application Entity Title Not Recognized". - * The standard handler always returns OFTrue. - * @param callingAE The calling AE title the SCU used that should be checked - * @return OFTrue, if AE title is accepted, OFFalse otherwise - */ - virtual OFBool checkCallingAETitleAccepted(const OFString& callingAE); - - /** Overwrite this function if calling IP / host name should undergo checking. - * If OFTrue is returned, the host is accepted and processing is continued. - * In case of OFFalse, the SCP will refuse the incoming association with - * an error. The standard handler always returns OFTrue. - * @param hostOrIP The IP of the client to check. - * @return OFTrue, if IP/host is accepted, OFFalse otherwise - */ - virtual OFBool checkCallingHostAccepted(const OFString& hostOrIP); - - /** Overwrite this function to be notified about an incoming association request. - * The standard handler only outputs some information to the logger. - */ - virtual void notifyAssociationAcknowledge(); - - /** Overwrite this function to be notified about an incoming association release request. - * The standard handler only outputs some information to the logger. - */ - virtual void notifyReleaseRequest(); - - /** Overwrite this function to be notified about an incoming association abort request. - * The standard handler only outputs some information to the logger. - */ - virtual void notifyAbortRequest(); - - /** Overwrite this function to be notified when an association is terminated. - * The standard handler only outputs some information to the logger. - */ - virtual void notifyAssociationTermination(); - - /** Overwrite this function to be notified about a connection timeout in - * non-blocking mode (see setConnectionBlockingMode() and setConnectionTimeout() - * methods). In blocking mode, this method has no effect since it's never called. - * The standard handler only outputs some information to the TRACE logger. - */ - virtual void notifyConnectionTimeout(); - - /** Overwrite this function to be notified when a DIMSE error occurs. - * The standard handler only outputs error information to the logger. - * @param cond [in] The DIMSE error occurred. - */ - virtual void notifyDIMSEError(const OFCondition &cond); - - /** This function is called while sending DIMSE messages, i.e.\ on each PDV of a dataset. - * The default implementation just prints a TRACE message on the number of bytes sent so - * far. By overwriting this method, the progress of the send process can be shown to the - * user in a more appropriate way. The progress notification can also be disabled - * completely by calling setProgressNotificationMode(). - * @param byteCount [in] Number of bytes sent so far - */ - virtual void notifySENDProgress(const unsigned long byteCount); - - /** This function is called while receiving DIMSE messages, i.e.\ on each PDV of a dataset. - * The default implementation just prints a TRACE message on the number of bytes received - * so far. By overwriting this method, the progress of the receive process can be shown to - * the user in a more appropriate way. The progress notification can also be disabled - * completely by calling setProgressNotificationMode(). - * @param byteCount [in] Number of bytes received so far - */ - virtual void notifyRECEIVEProgress(const unsigned long byteCount); - - /** This method can be used to return from the listen() loop in a controlled way. - * In order to use it, it must be overwritten in a derived class. As long as no - * severe error occurs and this method returns OFFalse, the listen() method will wait - * for incoming associations in an infinite loop. - * @return The standard handler always returns OFFalse - */ - virtual OFBool stopAfterCurrentAssociation(); - - /** This method can be used to return from the listen() loop in a controlled way. - * In order to use it, it must be overwritten in a derived class. As long as no - * severe error occurs and this method returns OFFalse, the listen() method will wait - * for incoming associations in an infinite loop. If this method returns OFTrue, the - * SCP will return from the listen() loop after a connection timeout occurs (see - * setConnectionTimeout() method). In blocking mode (see setConnectionBlockingMode() - * method), this method has no effect (it's never called) since the underlying - * routines will wait forever for an incoming TCP connection. - * @return The standard handler always returns OFFalse - */ - virtual OFBool stopAfterConnectionTimeout(); - - // -- C-ECHO -- - - /** Standard handler for Verification Service Class (DICOM Echo). Returns echo response - * (i.e. whether C-ECHO could be responded to with status success). - * @param reqMessage [in] The C-ECHO request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleECHORequest(T_DIMSE_C_EchoRQ &reqMessage, - const T_ASC_PresentationContextID presID); - - // --- C-STORE -- - - /** Receive C-STORE request on the currently opened association, store the - * accompanying dataset in memory and send a corresponding response. Calls - * checkSTORERequest() in order to determine the DIMSE status code to be used for - * the C-STORE response. - * @note This handler receives the dataset belonging the C-STORE request completely - * in memory. If very large datasets are expected, another handler should be - * implemented that calls the receiveSTORERequest() method with a filename. - * @param reqMessage [in] The C-STORE request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [inout] Pointer to data structure where the received dataset - * should be stored. If NULL, a new dataset is created, - * which has to be deleted by the caller. - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset); - - /** Receive C-STORE request (and store accompanying dataset in memory). - * For very large datasets, the other receiveSTORERequest() method should be used - * because it stores the received dataset directly to file. - * @param reqMessage [in] The C-STORE request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [inout] Pointer to data structure where the received dataset - * should be stored. If NULL, a new dataset is created, - * which has to be deleted by the caller. - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition receiveSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset); - - /** Receive C-STORE request (and store accompanying dataset directly to file). - * The dataset is stored exactly as received, i.e. without any conversions. - * @param reqMessage [in] The C-STORE request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param filename [in] The filename used to store the received dataset - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition receiveSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, - const T_ASC_PresentationContextID presID, - const OFString &filename); - - /** Respond to the C-STORE request (with details from the request message) - * @param presID [in] The presentation context ID to respond to - * @param reqMessage [in] The C-STORE request that should be responded to - * @param rspStatusCode [in] The response status code. 0 means success, - * others can found in the DICOM standard. - * @return EC_Normal, if responding was successful, an error code otherwise - */ - virtual OFCondition sendSTOREResponse(const T_ASC_PresentationContextID presID, - const T_DIMSE_C_StoreRQ &reqMessage, - const Uint16 rspStatusCode); - - /** Respond to the C-STORE request (with given details) - * @param presID [in] The presentation context ID to respond to - * @param messageID [in] The message ID being responded to - * @param sopClassUID [in] The affected SOP class UID - * @param sopInstanceUID [in] The affected SOP instance UID - * @param rspStatusCode [in] The response status code. 0 means success, - * others can found in the DICOM standard. - * @param statusDetail [in] The status detail of the response (if desired). - * @return EC_Normal, if responding was successful, an error code otherwise - */ - virtual OFCondition sendSTOREResponse(const T_ASC_PresentationContextID presID, - const Uint16 messageID, - const OFString &sopClassUID, - const OFString &sopInstanceUID, - const Uint16 rspStatusCode, - DcmDataset *statusDetail = NULL); - - /** Check given C-STORE request and dataset for validity. This method is called by - * handleSTORERequest() before sending the response in order to determine the DIMSE - * status code to be used for the response message. - * @param reqMessage [in] The C-STORE request message data structure - * @param reqDataset [in] The C-STORE request dataset received. Might be NULL. - * @return DIMSE status code to be used for the C-STORE response. - * Always returns STATUS_Success (0). Derived classes should, therefore, - * overwrite this method and return a more appropriate value based on the - * result of the checks performed. - */ - virtual Uint16 checkSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, - DcmDataset *reqDataset); - - // -- C-FIND -- - - /** Receive C-FIND request - * @param reqMessage [in] The C-FIND request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition receiveFINDRequest(T_DIMSE_C_FindRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset); - - /** Handle C-FIND request. This function is deprecated and will be removed in - * the future. For now it calls receiveFINDRequest() which should be used - * instead. - * @param reqMessage [in] The C-FIND request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleFINDRequest(T_DIMSE_C_FindRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset) - { - DCMNET_WARN("handleFINDRequest() is deprecated, use receiveFINDRequest() instead"); - return receiveFINDRequest(reqMessage, presID, reqDataset); - } - - /** Respond to the C-FIND request - * @param presID [in] The presentation context ID to respond to - * @param messageID [in] The message ID being responded to - * @param sopClassUID [in] The affected SOP class UID - * @param rspDataset [in] The response dataset - * @param rspStatusCode [in] The response status code. 0 means success, - * others can found in the DICOM standard. - * @param statusDetail [in] Any status (must fit response code), if desired - * @return EC_Normal, if responding was successful, an error code otherwise - */ - virtual OFCondition sendFINDResponse(const T_ASC_PresentationContextID presID, - const Uint16 messageID, - const OFString &sopClassUID, - DcmDataset *rspDataset, - const Uint16 rspStatusCode, - DcmDataset* statusDetail = NULL); - - /** Check for C-CANCEL. This is needed for example for a Query/Retrieve - * server that is in the middle of returning C-FIND responses to a - * client and has to perform a regular check whether the client sent a - * C-CANCEL in order to stop receiving C-FIND responses. - * @param presID [in] The presentation context ID where C-CANCEL is - * expected. - * @param messageID [in] The "message ID responded to" that the client - * is expected to use (usually this is the message - * ID used in the original FIND/GET/MOVE request). - * @return EC_Normal, if C-CANCEL was received. DIMSE_NODATAAVAILABLE if no - * DIMSE message (or anything) was received from the client. - * DIMSEC_UNEXPECTEDREQUEST if command is received but it is not - * a C-CANCEL message, or the message ID used by client is wrong - * (message ID must be the one from the original FIND/MOVE/GET - * request). - * DIMSEC_INVALIDPRESENTATIONCONTEXTID if the wrong presentation - * context (ID) was used for sending. Other low level errors - * (e.g. DIMSEC_UNEXPECTEDPDVTYPE) could be returned, too. - */ - virtual OFCondition checkForCANCEL(T_ASC_PresentationContextID presID, - const Uint16 messageID); - - // --- C-MOVE -- - - /** Receive C-MOVE request on the currently active association. - * @param reqMessage [in] The C-MOVE request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @param moveDest [out] The move destination where to send the instances - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition receiveMOVERequest(T_DIMSE_C_MoveRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - OFString &moveDest); - - /** Receive C-MOVE request on the currently active association. This function - * is deprecated and will be removed in the future. For now it calls - * receiveMOVERequest() which should be used instead. - * @param reqMessage [in] The C-MOVE request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @param moveDest [out] The move destination where to send the instances - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleMOVERequest(T_DIMSE_C_MoveRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - OFString &moveDest) - { - DCMNET_WARN("handleMOVERequest() is deprecated, use receiveMOVERequest() instead"); - return receiveMOVERequest(reqMessage, presID, reqDataset, moveDest); - } - - /** Respond to the C-MOVE request - * @param presID [in] The presentation context ID to respond to - * @param messageID [in] The message ID being responded to - * @param sopClassUID [in] The affected SOP class UID - * @param rspDataset [in] The response dataset - * @param rspStatusCode [in] The status code of the response. 0 means success, - * others can found in the DICOM standard. - * @param statusDetail [in] The status detail of the response (if desired). - * @param numRemain [in] Number of remaining sub-operations. - * Required for Pending status codes, often optional otherwise. - * Sent if one of the num parameters is not 0. - * @param numComplete [in] Number of completed sub-operations. - * Required for Pending status codes, often optional otherwise. - * Sent if one of the num parameters is not 0. - * @param numFail [in] Number of failed sub-operations. - * Required for Pending status codes, often optional otherwise. - * Sent if one of the num parameters is not 0. - * @param numWarn [in] Number of warning sub-operations. - * Required for Pending status codes, often optional otherwise. - * Sent if one of the num parameters is not 0. - * @return EC_Normal, if responding was successful, an error code otherwise - */ - virtual OFCondition sendMOVEResponse(const T_ASC_PresentationContextID presID, - const Uint16 messageID, - const OFString &sopClassUID, - DcmDataset *rspDataset, - const Uint16 rspStatusCode, - DcmDataset *statusDetail = NULL, - const Uint16 numRemain = 0, - const Uint16 numComplete = 0, - const Uint16 numFail = 0, - const Uint16 numWarn = 0); - - // -- N-ACTION -- - - /** Receive N-ACTION request on the currently opened association. - * @param reqMessage [in] The N-ACTION request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @param actionTypeID [out] Action Type ID from the command set received - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition receiveACTIONRequest(T_DIMSE_N_ActionRQ &reqMessage, + /* ********************************************* */ + /* Functions available to derived classes only */ + /* ********************************************* */ + + /** This call returns the presentation context belonging to the given + * presentation context ID. + * @param presID [in] The presentation context ID to look for + * @param abstractSyntax [out] The abstract syntax (UID) for that ID. + * Empty, if such a presentation context does not exist. + * @param transferSyntax [out] The transfer syntax (UID) for that ID. + * Empty, if such a presentation context does not exist. + */ + void findPresentationContext(const T_ASC_PresentationContextID presID, + OFString& abstractSyntax, + OFString& transferSyntax); + + /** Aborts the current association by sending an A-ABORT request to the SCU. + * This method allows derived classes to abort an association in case of severe errors. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition abortAssociation(); + + /* *********************************************************************** */ + /* Functions particularly interesting for overwriting in derived classes */ + /* *********************************************************************** */ + + /** Handle incoming command set and react accordingly, e.g.\ sending response via + * DIMSE_sendXXXResponse(). The standard handler only knows how to handle + * a C-ECHO request message (by calling handleEchoRequest()) if it is sent on a + * presentation context configured for the Verification SOP Class. + * This function is most likely to be implemented by a derived class + * implementing a specific SCP behavior. + * @param incomingMsg The DIMSE message received + * @param presInfo Additional information on the Presentation Context used + * @return EC_Normal if the message could be handled, error if not. Especially + * DIMSE_BADCOMMANDTYPE should be returned if there is no handler for + * this particular type of DIMSE message. E.g. the default handler in + * DcmSCP only handles C-ECHO requests and, therefore, returns + * DIMSE_BADCOMMANDTYPE otherwise. + */ + virtual OFCondition handleIncomingCommand(T_DIMSE_Message* incomingMsg, const DcmPresentationContextInfo& presInfo); + + /** Overwrite this function to be notified about an incoming association request. + * The standard handler only outputs some information to the logger. + * @param params The association parameters that were received. + * @param desiredAction The desired action how to handle this association request. + */ + virtual void notifyAssociationRequest(const T_ASC_Parameters& params, DcmSCPActionType& desiredAction); + + /** Overwrite this function if called AE title should undergo checking. If + * OFTrue is returned, the AE title is accepted and processing is continued. + * In case of OFFalse, the SCP will refuse the incoming association with + * error "Called Application Entity Title Not Recognized". + * The standard handler always returns OFTrue. + * @param calledAE The called AE title the SCU used that should be checked + * @return OFTrue, if AE title is accepted, OFFalse otherwise + */ + virtual OFBool checkCalledAETitleAccepted(const OFString& calledAE); + + /** Overwrite this function if calling AE title should undergo checking. If + * OFTrue is returned, the AE title is accepted and processing is continued. + * In case of OFFalse, the SCP will refuse the incoming association with + * error "Calling Application Entity Title Not Recognized". + * The standard handler always returns OFTrue. + * @param callingAE The calling AE title the SCU used that should be checked + * @return OFTrue, if AE title is accepted, OFFalse otherwise + */ + virtual OFBool checkCallingAETitleAccepted(const OFString& callingAE); + + /** Overwrite this function if calling IP / host name should undergo checking. + * If OFTrue is returned, the host is accepted and processing is continued. + * In case of OFFalse, the SCP will refuse the incoming association with + * an error. The standard handler always returns OFTrue. + * @param hostOrIP The IP of the client to check. + * @return OFTrue, if IP/host is accepted, OFFalse otherwise + */ + virtual OFBool checkCallingHostAccepted(const OFString& hostOrIP); + + /** Overwrite this function to be notified about an incoming association request. + * The standard handler only outputs some information to the logger. + */ + virtual void notifyAssociationAcknowledge(); + + /** Overwrite this function to be notified about an incoming association release request. + * The standard handler only outputs some information to the logger. + */ + virtual void notifyReleaseRequest(); + + /** Overwrite this function to be notified about an incoming association abort request. + * The standard handler only outputs some information to the logger. + */ + virtual void notifyAbortRequest(); + + /** Overwrite this function to be notified when an association is terminated. + * The standard handler only outputs some information to the logger. + */ + virtual void notifyAssociationTermination(); + + /** Overwrite this function to be notified about a connection timeout in + * non-blocking mode (see setConnectionBlockingMode() and setConnectionTimeout() + * methods). In blocking mode, this method has no effect since it's never called. + * The standard handler only outputs some information to the TRACE logger. + */ + virtual void notifyConnectionTimeout(); + + /** Overwrite this function to be notified when a DIMSE error occurs. + * The standard handler only outputs error information to the logger. + * @param cond [in] The DIMSE error occurred. + */ + virtual void notifyDIMSEError(const OFCondition& cond); + + /** This function is called while sending DIMSE messages, i.e.\ on each PDV of a dataset. + * The default implementation just prints a TRACE message on the number of bytes sent so + * far. By overwriting this method, the progress of the send process can be shown to the + * user in a more appropriate way. The progress notification can also be disabled + * completely by calling setProgressNotificationMode(). + * @param byteCount [in] Number of bytes sent so far + */ + virtual void notifySENDProgress(const unsigned long byteCount); + + /** This function is called while receiving DIMSE messages, i.e.\ on each PDV of a dataset. + * The default implementation just prints a TRACE message on the number of bytes received + * so far. By overwriting this method, the progress of the receive process can be shown to + * the user in a more appropriate way. The progress notification can also be disabled + * completely by calling setProgressNotificationMode(). + * @param byteCount [in] Number of bytes received so far + */ + virtual void notifyRECEIVEProgress(const unsigned long byteCount); + + /** This method can be used to return from the listen() loop in a controlled way. + * In order to use it, it must be overwritten in a derived class. As long as no + * severe error occurs and this method returns OFFalse, the listen() method will wait + * for incoming associations in an infinite loop. + * @return The standard handler always returns OFFalse + */ + virtual OFBool stopAfterCurrentAssociation(); + + /** This method can be used to return from the listen() loop in a controlled way. + * In order to use it, it must be overwritten in a derived class. As long as no + * severe error occurs and this method returns OFFalse, the listen() method will wait + * for incoming associations in an infinite loop. If this method returns OFTrue, the + * SCP will return from the listen() loop after a connection timeout occurs (see + * setConnectionTimeout() method). In blocking mode (see setConnectionBlockingMode() + * method), this method has no effect (it's never called) since the underlying + * routines will wait forever for an incoming TCP connection. + * @return The standard handler always returns OFFalse + */ + virtual OFBool stopAfterConnectionTimeout(); + + // -- C-ECHO -- + + /** Standard handler for Verification Service Class (DICOM Echo). Returns echo response + * (i.e. whether C-ECHO could be responded to with status success). + * @param reqMessage [in] The C-ECHO request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleECHORequest(T_DIMSE_C_EchoRQ& reqMessage, const T_ASC_PresentationContextID presID); + + // --- C-STORE -- + + /** Receive C-STORE request on the currently opened association, store the + * accompanying dataset in memory and send a corresponding response. Calls + * checkSTORERequest() in order to determine the DIMSE status code to be used for + * the C-STORE response. + * @note This handler receives the dataset belonging the C-STORE request completely + * in memory. If very large datasets are expected, another handler should be + * implemented that calls the receiveSTORERequest() method with a filename. + * @param reqMessage [in] The C-STORE request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [inout] Pointer to data structure where the received dataset + * should be stored. If NULL, a new dataset is created, + * which has to be deleted by the caller. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset); + + /** Receive C-STORE request (and store accompanying dataset in memory). + * For very large datasets, the other receiveSTORERequest() method should be used + * because it stores the received dataset directly to file. + * @param reqMessage [in] The C-STORE request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [inout] Pointer to data structure where the received dataset + * should be stored. If NULL, a new dataset is created, + * which has to be deleted by the caller. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition receiveSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset); + + /** Receive C-STORE request (and store accompanying dataset directly to file). + * The dataset is stored exactly as received, i.e. without any conversions. + * @param reqMessage [in] The C-STORE request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param filename [in] The filename used to store the received dataset + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition receiveSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, + const T_ASC_PresentationContextID presID, + const OFString& filename); + + /** Respond to the C-STORE request (with details from the request message) + * @param presID [in] The presentation context ID to respond to + * @param reqMessage [in] The C-STORE request that should be responded to + * @param rspStatusCode [in] The response status code. 0 means success, + * others can found in the DICOM standard. + * @return EC_Normal, if responding was successful, an error code otherwise + */ + virtual OFCondition sendSTOREResponse(const T_ASC_PresentationContextID presID, + const T_DIMSE_C_StoreRQ& reqMessage, + const Uint16 rspStatusCode); + + /** Respond to the C-STORE request (with given details) + * @param presID [in] The presentation context ID to respond to + * @param messageID [in] The message ID being responded to + * @param sopClassUID [in] The affected SOP class UID + * @param sopInstanceUID [in] The affected SOP instance UID + * @param rspStatusCode [in] The response status code. 0 means success, + * others can found in the DICOM standard. + * @param statusDetail [in] The status detail of the response (if desired). + * @return EC_Normal, if responding was successful, an error code otherwise + */ + virtual OFCondition sendSTOREResponse(const T_ASC_PresentationContextID presID, + const Uint16 messageID, + const OFString& sopClassUID, + const OFString& sopInstanceUID, + const Uint16 rspStatusCode, + DcmDataset* statusDetail = NULL); + + /** Check given C-STORE request and dataset for validity. This method is called by + * handleSTORERequest() before sending the response in order to determine the DIMSE + * status code to be used for the response message. + * @param reqMessage [in] The C-STORE request message data structure + * @param reqDataset [in] The C-STORE request dataset received. Might be NULL. + * @return DIMSE status code to be used for the C-STORE response. + * Always returns STATUS_Success (0). Derived classes should, therefore, + * overwrite this method and return a more appropriate value based on the + * result of the checks performed. + */ + virtual Uint16 checkSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, DcmDataset* reqDataset); + + // -- C-FIND -- + + /** Receive C-FIND request + * @param reqMessage [in] The C-FIND request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + receiveFINDRequest(T_DIMSE_C_FindRQ& reqMessage, const T_ASC_PresentationContextID presID, DcmDataset*& reqDataset); + + /** Handle C-FIND request. This function is deprecated and will be removed in + * the future. For now it calls receiveFINDRequest() which should be used + * instead. + * @param reqMessage [in] The C-FIND request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + handleFINDRequest(T_DIMSE_C_FindRQ& reqMessage, const T_ASC_PresentationContextID presID, DcmDataset*& reqDataset) + { + DCMNET_WARN("handleFINDRequest() is deprecated, use receiveFINDRequest() instead"); + return receiveFINDRequest(reqMessage, presID, reqDataset); + } + + /** Respond to the C-FIND request + * @param presID [in] The presentation context ID to respond to + * @param messageID [in] The message ID being responded to + * @param sopClassUID [in] The affected SOP class UID + * @param rspDataset [in] The response dataset + * @param rspStatusCode [in] The response status code. 0 means success, + * others can found in the DICOM standard. + * @param statusDetail [in] Any status (must fit response code), if desired + * @return EC_Normal, if responding was successful, an error code otherwise + */ + virtual OFCondition sendFINDResponse(const T_ASC_PresentationContextID presID, + const Uint16 messageID, + const OFString& sopClassUID, + DcmDataset* rspDataset, + const Uint16 rspStatusCode, + DcmDataset* statusDetail = NULL); + + /** Check for C-CANCEL. This is needed for example for a Query/Retrieve + * server that is in the middle of returning C-FIND responses to a + * client and has to perform a regular check whether the client sent a + * C-CANCEL in order to stop receiving C-FIND responses. + * @param presID [in] The presentation context ID where C-CANCEL is + * expected. + * @param messageID [in] The "message ID responded to" that the client + * is expected to use (usually this is the message + * ID used in the original FIND/GET/MOVE request). + * @return EC_Normal, if C-CANCEL was received. DIMSE_NODATAAVAILABLE if no + * DIMSE message (or anything) was received from the client. + * DIMSEC_UNEXPECTEDREQUEST if command is received but it is not + * a C-CANCEL message, or the message ID used by client is wrong + * (message ID must be the one from the original FIND/MOVE/GET + * request). + * DIMSEC_INVALIDPRESENTATIONCONTEXTID if the wrong presentation + * context (ID) was used for sending. Other low level errors + * (e.g. DIMSEC_UNEXPECTEDPDVTYPE) could be returned, too. + */ + virtual OFCondition checkForCANCEL(T_ASC_PresentationContextID presID, const Uint16 messageID); + + // --- C-MOVE -- + + /** Receive C-MOVE request on the currently active association. + * @param reqMessage [in] The C-MOVE request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @param moveDest [out] The move destination where to send the instances + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition receiveMOVERequest(T_DIMSE_C_MoveRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - Uint16 &actionTypeID); - - /** Receive N-ACTION request on the currently opened association. This - * function is deprecated and will be removed in the future. For now it calls - * receiveACTIONRequest() which should be used instead. - * @param reqMessage [in] The N-ACTION request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @param actionTypeID [out] Action Type ID from the command set received - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleACTIONRequest(T_DIMSE_N_ActionRQ &reqMessage, + DcmDataset*& reqDataset, + OFString& moveDest); + + /** Receive C-MOVE request on the currently active association. This function + * is deprecated and will be removed in the future. For now it calls + * receiveMOVERequest() which should be used instead. + * @param reqMessage [in] The C-MOVE request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @param moveDest [out] The move destination where to send the instances + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleMOVERequest(T_DIMSE_C_MoveRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - Uint16 &actionTypeID) - { - DCMNET_WARN("handleACTIONRequest() is deprecated, use receiveACTIONRequest() instead"); - return receiveACTIONRequest(reqMessage, presID, reqDataset, actionTypeID); - } - - /** Respond to the N-ACTION request - * @param presID [in] The presentation context ID to respond to - * @param messageID [in] The message ID being responded to - * @param sopClassUID [in] The affected SOP class UID - * @param sopInstanceUID [in] The affected SOP instance UID - * @param rspStatusCode [in] The response status code. 0 means success, - * others can found in the DICOM standard. - * @return EC_Normal, if responding was successful, an error code otherwise - */ - virtual OFCondition sendACTIONResponse(const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset, + OFString& moveDest) + { + DCMNET_WARN("handleMOVERequest() is deprecated, use receiveMOVERequest() instead"); + return receiveMOVERequest(reqMessage, presID, reqDataset, moveDest); + } + + /** Respond to the C-MOVE request + * @param presID [in] The presentation context ID to respond to + * @param messageID [in] The message ID being responded to + * @param sopClassUID [in] The affected SOP class UID + * @param rspDataset [in] The response dataset + * @param rspStatusCode [in] The status code of the response. 0 means success, + * others can found in the DICOM standard. + * @param statusDetail [in] The status detail of the response (if desired). + * @param numRemain [in] Number of remaining sub-operations. + * Required for Pending status codes, often optional otherwise. + * Sent if one of the num parameters is not 0. + * @param numComplete [in] Number of completed sub-operations. + * Required for Pending status codes, often optional otherwise. + * Sent if one of the num parameters is not 0. + * @param numFail [in] Number of failed sub-operations. + * Required for Pending status codes, often optional otherwise. + * Sent if one of the num parameters is not 0. + * @param numWarn [in] Number of warning sub-operations. + * Required for Pending status codes, often optional otherwise. + * Sent if one of the num parameters is not 0. + * @return EC_Normal, if responding was successful, an error code otherwise + */ + virtual OFCondition sendMOVEResponse(const T_ASC_PresentationContextID presID, const Uint16 messageID, - const OFString &sopClassUID, - const OFString &sopInstanceUID, - const Uint16 rspStatusCode); - - // -- N-EVENT-REPORT -- - - /** Receive N-EVENT-REPORT request on the currently opened association and send a - * corresponding response. Calls checkEVENTREPORTRequest() in order to determine the - * DIMSE status code to be used for the N-EVENT-REPORT response. - * @param reqMessage [in] The N-EVENT-REPORT request message that was received - * @param presID [in] The presentation context to be used. By default, the - * presentation context of the request is used. - * @param reqDataset [out] Pointer to the dataset received - * @param eventTypeID [out] Event Type ID from the command set received - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleEVENTREPORTRequest(T_DIMSE_N_EventReportRQ &reqMessage, - const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - Uint16 &eventTypeID); - - /** Send N-EVENT-REPORT request on the current association and receive a corresponding - * response. - * @param presID [in] The ID of the presentation context to be used for sending - * the request message. Should not be 0. - * @param sopInstanceUID [in] The requested SOP Instance UID - * @param messageID [in] The request message ID - * @param eventTypeID [in] The event type ID to be used - * @param reqDataset [in] The request dataset to be sent - * @param rspStatusCode [out] The response status code received. 0 means success, - * others can be found in the DICOM standard. - * @return EC_Normal if request could be issued and response was received successfully, - * an error code otherwise - */ - virtual OFCondition sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, - const Uint16 messageID, - const Uint16 eventTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode); - - /** Check given N-EVENT-REPORT request and dataset for validity. This method is called by - * handleEVENTREPORTRequest() before sending the response in order to determine the - * DIMSE status code to be used for the response message. - * @param reqMessage [in] The N-EVENT-REPORT request message data structure - * @param reqDataset [in] The N-EVENT-REPORT request dataset received. Might be NULL. - * @return DIMSE status code to be used for the N-EVENT-REPORT response. - * Always returns STATUS_Success (0). Derived classes should, therefore, - * overwrite this method and return a more appropriate value based on the - * result of the checks performed. - */ - virtual Uint16 checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ &reqMessage, - DcmDataset *reqDataset); - - /* ********************************************************************* */ - /* Further functions and member variables */ - /* ********************************************************************* */ - - /** Helper function to return presentation context information by given - * presentation context ID. - * @param head The presentation context list - * @param presentationContextID The presentation context ID - * @return The presentation context information - */ - static DUL_PRESENTATIONCONTEXT* findPresentationContextID(LST_HEAD *head, - T_ASC_PresentationContextID presentationContextID); - - /** Helper function to return presentation context information by given - * presentation context ID. - * @param assoc The association to search - * @param presID The presentation context ID - * @param presInfo The result presentation context information, if found - * @return OFTrue if presentation context with ID could be found, OFFalse - * otherwise - */ - static OFBool getPresentationContextInfo(const T_ASC_Association *assoc, - const Uint8 presID, - DcmPresentationContextInfo &presInfo); - - /** This function takes care of receiving, negotiating and accepting/refusing an - * association request. Additionally, if negotiation was successful, it handles any - * incoming DIMSE commands by calling handleAssociation(). An error is only returned, if - * something goes wrong. Therefore, refusing an association because of wrong application - * context name or no common presentation contexts with the SCU does NOT lead to an error. - * @param network [in] Contains network parameters - * @return EC_Normal, if everything went fine, DUL_NOASSOCIATIONREQUEST if a timeout - * occurs in non-blocking mode, DIMSE_ILLEGALASSOCIATION or ASC_NULLKEY if - * severe internal errors occured (should not happen) - */ - virtual OFCondition waitForAssociationRQ(T_ASC_Network *network); - - /** Actually process association request. - * @return EC_Normal if association could be processed, ASC_NULLKEY otherwise - * (only if internal association structure is invalid, should never happen) - */ - virtual OFCondition processAssociationRQ(); - - /** This function checks all presentation contexts proposed by the SCU whether they are - * supported or not. It is not an error if no common presentation context could be - * identified with the SCU; only issues like problems in memory management etc. are - * reported as an error. This function does not send a response message to the SCU. This - * is done in other functions. - * @return EC_Normal if negotiation was successfully done, an error code otherwise - */ - virtual OFCondition negotiateAssociation(); - - /** This function takes care of refusing an association request - * @param reason [in] The reason why the association request will be refused and that - * will be reported to the SCU. - */ - virtual void refuseAssociation(const DcmRefuseReasonType reason); - - /** This function takes care of handling the other DICOM application's request. After - * having accomplished all necessary steps, the association will be dropped and destroyed. - */ - virtual void handleAssociation(); - - /** Send a DIMSE command and possibly also a dataset from a data object via network to - * another DICOM application - * @param presID [in] Presentation context ID to be used for message - * @param message [in] Structure that represents a certain DIMSE command which - * shall be sent - * @param dataObject [in] The instance data which shall be sent to the other DICOM - * application; NULL, if there is none - * @param statusDetail [in] The status detail of the response (if desired). - * @param commandSet [out] If this parameter is not NULL it will return a copy of the - * DIMSE command which is sent to the other DICOM application - * @return Returns EC_Normal if sending request was successful, an error code otherwise - */ - OFCondition sendDIMSEMessage(const T_ASC_PresentationContextID presID, - T_DIMSE_Message *message, - DcmDataset *dataObject, - DcmDataset *statusDetail = NULL, - DcmDataset **commandSet = NULL); - - /** Receive DIMSE command (excluding dataset!) over the currently open association - * @param presID [out] Contains in the end the ID of the presentation context - * which was specified in the DIMSE command received - * @param message [out] The message received - * @param statusDetail [out] If a non-NULL value is passed this variable will in the end - * contain detailed information with regard to the status - * information which is captured in the status element - * (0000,0900). Note that the value for element (0000,0900) is - * not contained in this return value but in internal message. - * For details on the structure of this object, see DICOM - * standard part 7, annex C). - * @param commandSet [out] If this parameter is not NULL, it will return a copy of the - * DIMSE command which was received from the other DICOM - * application. The caller is responsible to de-allocate the - * returned object! - * @param timeout [in] If this parameter is not 0, it specifies the timeout (in - * seconds) to be used for receiving the DIMSE command. - * Otherwise, the default timeout value is used (see - * setDIMSETimeout()). - * @return EC_Normal if command could be received successfully, an error code otherwise - */ - OFCondition receiveDIMSECommand(T_ASC_PresentationContextID *presID, - T_DIMSE_Message *message, - DcmDataset **statusDetail, - DcmDataset **commandSet = NULL, - const Uint32 timeout = 0); - - /** Receive one dataset (of instance data) via network from another DICOM application - * @param presID [out] Contains in the end the ID of the presentation context - * which was used in the PDVs that were received on the - * network. If the PDVs show different presentation context - * IDs, this function will return an error. - * @param dataObject [inout] Contains in the end the information that was received - * over the network. If this parameter points to NULL, a new - * dataset will be created by the underlying routines, which - * has to be deleted by the caller. - * @return EC_Normal if dataset could be received successfully, an error code otherwise - */ - OFCondition receiveDIMSEDataset(T_ASC_PresentationContextID *presID, - DcmDataset **dataObject); - - /** Receive one C-STORE request dataset via network from another DICOM application and - * store it directly to file (i.e.\ exactly as received without any conversions) - * @param presID [inout] Initially, the presentation context the C-STORE request was - * received on. Contains in the end the ID of the presentation - * context which was used in the PDVs that were received on the - * network. If the PDVs show different presentation context - * IDs, this function will return an error. - * @param reqMessage [in] The C-STORE request message that was received - * @param filename [in] Name of the file that is created to store the received dataset - * @return EC_Normal if dataset could be received successfully, an error code otherwise - */ - OFCondition receiveSTORERequestDataset(T_ASC_PresentationContextID *presID, - T_DIMSE_C_StoreRQ &reqMessage, - const OFString &filename); - - /** Add given element to existing status detail object or create new one. - * @param statusDetail The status detail to add the element to. Status detail - * is information additional to the DIMSE status code which can be - * provided for some DIMSE messages. If NULL is provided, - * a new status detail object is created and returned. All status - * detail attributes need to have the VR AT or LO which is also - * checked by the underlying routine. - * @param elem The element to be copied into the status detail. - * @return OFTrue if status detail was successfully added, - * OFFalse otherwise. - */ - static OFBool addStatusDetail(DcmDataset **statusDetail, - const DcmElement *elem); - - /* Callback functions (static) */ - - /** Callback function used for sending DIMSE messages. - * @param callbackContext [in] The desired user callback data - * @param byteCount [in] Progress bytes count - */ - static void callbackSENDProgress(void *callbackContext, - unsigned long byteCount); - - /** Callback function used for receiving DIMSE messages. - * @param callbackContext [in] The desired user callback data - * @param byteCount [in] Progress bytes count - */ - static void callbackRECEIVEProgress(void *callbackContext, - unsigned long byteCount); + const OFString& sopClassUID, + DcmDataset* rspDataset, + const Uint16 rspStatusCode, + DcmDataset* statusDetail = NULL, + const Uint16 numRemain = 0, + const Uint16 numComplete = 0, + const Uint16 numFail = 0, + const Uint16 numWarn = 0); + + // -- N-ACTION -- + + /** Receive N-ACTION request on the currently opened association. + * @param reqMessage [in] The N-ACTION request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @param actionTypeID [out] Action Type ID from the command set received + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition receiveACTIONRequest(T_DIMSE_N_ActionRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset, + Uint16& actionTypeID); + + /** Receive N-ACTION request on the currently opened association. This + * function is deprecated and will be removed in the future. For now it calls + * receiveACTIONRequest() which should be used instead. + * @param reqMessage [in] The N-ACTION request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @param actionTypeID [out] Action Type ID from the command set received + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleACTIONRequest(T_DIMSE_N_ActionRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset, + Uint16& actionTypeID) + { + DCMNET_WARN("handleACTIONRequest() is deprecated, use receiveACTIONRequest() instead"); + return receiveACTIONRequest(reqMessage, presID, reqDataset, actionTypeID); + } + + /** Respond to the N-ACTION request + * @param presID [in] The presentation context ID to respond to + * @param messageID [in] The message ID being responded to + * @param sopClassUID [in] The affected SOP class UID + * @param sopInstanceUID [in] The affected SOP instance UID + * @param rspStatusCode [in] The response status code. 0 means success, + * others can found in the DICOM standard. + * @return EC_Normal, if responding was successful, an error code otherwise + */ + virtual OFCondition sendACTIONResponse(const T_ASC_PresentationContextID presID, + const Uint16 messageID, + const OFString& sopClassUID, + const OFString& sopInstanceUID, + const Uint16 rspStatusCode); + + // -- N-EVENT-REPORT -- + + /** Receive N-EVENT-REPORT request on the currently opened association and send a + * corresponding response. Calls checkEVENTREPORTRequest() in order to determine the + * DIMSE status code to be used for the N-EVENT-REPORT response. + * @param reqMessage [in] The N-EVENT-REPORT request message that was received + * @param presID [in] The presentation context to be used. By default, the + * presentation context of the request is used. + * @param reqDataset [out] Pointer to the dataset received + * @param eventTypeID [out] Event Type ID from the command set received + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset, + Uint16& eventTypeID); + + /** Send N-EVENT-REPORT request on the current association and receive a corresponding + * response. + * @param presID [in] The ID of the presentation context to be used for sending + * the request message. Should not be 0. + * @param sopInstanceUID [in] The requested SOP Instance UID + * @param messageID [in] The request message ID + * @param eventTypeID [in] The event type ID to be used + * @param reqDataset [in] The request dataset to be sent + * @param rspStatusCode [out] The response status code received. 0 means success, + * others can be found in the DICOM standard. + * @return EC_Normal if request could be issued and response was received successfully, + * an error code otherwise + */ + virtual OFCondition sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, + const OFString& sopInstanceUID, + const Uint16 messageID, + const Uint16 eventTypeID, + DcmDataset* reqDataset, + Uint16& rspStatusCode); + + /** Check given N-EVENT-REPORT request and dataset for validity. This method is called by + * handleEVENTREPORTRequest() before sending the response in order to determine the + * DIMSE status code to be used for the response message. + * @param reqMessage [in] The N-EVENT-REPORT request message data structure + * @param reqDataset [in] The N-EVENT-REPORT request dataset received. Might be NULL. + * @return DIMSE status code to be used for the N-EVENT-REPORT response. + * Always returns STATUS_Success (0). Derived classes should, therefore, + * overwrite this method and return a more appropriate value based on the + * result of the checks performed. + */ + virtual Uint16 checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& reqMessage, DcmDataset* reqDataset); + + /* ********************************************************************* */ + /* Further functions and member variables */ + /* ********************************************************************* */ + + /** Helper function to return presentation context information by given + * presentation context ID. + * @param head The presentation context list + * @param presentationContextID The presentation context ID + * @return The presentation context information + */ + static DUL_PRESENTATIONCONTEXT* findPresentationContextID(LST_HEAD* head, + T_ASC_PresentationContextID presentationContextID); + + /** Helper function to return presentation context information by given + * presentation context ID. + * @param assoc The association to search + * @param presID The presentation context ID + * @param presInfo The result presentation context information, if found + * @return OFTrue if presentation context with ID could be found, OFFalse + * otherwise + */ + static OFBool getPresentationContextInfo(const T_ASC_Association* assoc, + const Uint8 presID, + DcmPresentationContextInfo& presInfo); + + /** This function takes care of receiving, negotiating and accepting/refusing an + * association request. Additionally, if negotiation was successful, it handles any + * incoming DIMSE commands by calling handleAssociation(). An error is only returned, if + * something goes wrong. Therefore, refusing an association because of wrong application + * context name or no common presentation contexts with the SCU does NOT lead to an error. + * @param network [in] Contains network parameters + * @return EC_Normal, if everything went fine, DUL_NOASSOCIATIONREQUEST if a timeout + * occurs in non-blocking mode, DIMSE_ILLEGALASSOCIATION or ASC_NULLKEY if + * severe internal errors occurred (should not happen) + */ + virtual OFCondition waitForAssociationRQ(T_ASC_Network* network); + + /** Actually process association request. + * @return EC_Normal if association could be processed, ASC_NULLKEY otherwise + * (only if internal association structure is invalid, should never happen) + */ + virtual OFCondition processAssociationRQ(); + + /** This function checks all presentation contexts proposed by the SCU whether they are + * supported or not. It is not an error if no common presentation context could be + * identified with the SCU; only issues like problems in memory management etc. are + * reported as an error. This function does not send a response message to the SCU. This + * is done in other functions. + * @return EC_Normal if negotiation was successfully done, an error code otherwise + */ + virtual OFCondition negotiateAssociation(); + + /** This function takes care of refusing an association request + * @param reason [in] The reason why the association request will be refused and that + * will be reported to the SCU. + */ + virtual void refuseAssociation(const DcmRefuseReasonType reason); + + /** This function takes care of handling the other DICOM application's request. After + * having accomplished all necessary steps, the association will be dropped and destroyed. + */ + virtual void handleAssociation(); + + /** Send a DIMSE command and possibly also a dataset from a data object via network to + * another DICOM application + * @param presID [in] Presentation context ID to be used for message + * @param message [in] Structure that represents a certain DIMSE command which + * shall be sent + * @param dataObject [in] The instance data which shall be sent to the other DICOM + * application; NULL, if there is none + * @param statusDetail [in] The status detail of the response (if desired). + * @param commandSet [out] If this parameter is not NULL it will return a copy of the + * DIMSE command which is sent to the other DICOM application + * @return Returns EC_Normal if sending request was successful, an error code otherwise + */ + OFCondition sendDIMSEMessage(const T_ASC_PresentationContextID presID, + T_DIMSE_Message* message, + DcmDataset* dataObject, + DcmDataset* statusDetail = NULL, + DcmDataset** commandSet = NULL); + + /** Receive DIMSE command (excluding dataset!) over the currently open association + * @param presID [out] Contains in the end the ID of the presentation context + * which was specified in the DIMSE command received + * @param message [out] The message received + * @param statusDetail [out] If a non-NULL value is passed this variable will in the end + * contain detailed information with regard to the status + * information which is captured in the status element + * (0000,0900). Note that the value for element (0000,0900) is + * not contained in this return value but in internal message. + * For details on the structure of this object, see DICOM + * standard part 7, annex C). + * @param commandSet [out] If this parameter is not NULL, it will return a copy of the + * DIMSE command which was received from the other DICOM + * application. The caller is responsible to de-allocate the + * returned object! + * @param timeout [in] If this parameter is not 0, it specifies the timeout (in + * seconds) to be used for receiving the DIMSE command. + * Otherwise, the default timeout value is used (see + * setDIMSETimeout()). + * @return EC_Normal if command could be received successfully, an error code otherwise + */ + OFCondition receiveDIMSECommand(T_ASC_PresentationContextID* presID, + T_DIMSE_Message* message, + DcmDataset** statusDetail, + DcmDataset** commandSet = NULL, + const Uint32 timeout = 0); + + /** Receive one dataset (of instance data) via network from another DICOM application + * @param presID [out] Contains in the end the ID of the presentation context + * which was used in the PDVs that were received on the + * network. If the PDVs show different presentation context + * IDs, this function will return an error. + * @param dataObject [inout] Contains in the end the information that was received + * over the network. If this parameter points to NULL, a new + * dataset will be created by the underlying routines, which + * has to be deleted by the caller. + * @return EC_Normal if dataset could be received successfully, an error code otherwise + */ + OFCondition receiveDIMSEDataset(T_ASC_PresentationContextID* presID, DcmDataset** dataObject); + + /** Receive one C-STORE request dataset via network from another DICOM application and + * store it directly to file (i.e.\ exactly as received without any conversions) + * @param presID [inout] Initially, the presentation context the C-STORE request was + * received on. Contains in the end the ID of the presentation + * context which was used in the PDVs that were received on the + * network. If the PDVs show different presentation context + * IDs, this function will return an error. + * @param reqMessage [in] The C-STORE request message that was received + * @param filename [in] Name of the file that is created to store the received dataset + * @return EC_Normal if dataset could be received successfully, an error code otherwise + */ + OFCondition receiveSTORERequestDataset(T_ASC_PresentationContextID* presID, + T_DIMSE_C_StoreRQ& reqMessage, + const OFString& filename); + + /** Add given element to existing status detail object or create new one. + * @param statusDetail The status detail to add the element to. Status detail + * is information additional to the DIMSE status code which can be + * provided for some DIMSE messages. If NULL is provided, + * a new status detail object is created and returned. All status + * detail attributes need to have the VR AT or LO which is also + * checked by the underlying routine. + * @param elem The element to be copied into the status detail. + * @return OFTrue if status detail was successfully added, + * OFFalse otherwise. + */ + static OFBool addStatusDetail(DcmDataset** statusDetail, const DcmElement* elem); + + /* Callback functions (static) */ + + /** Callback function used for sending DIMSE messages. + * @param callbackContext [in] The desired user callback data + * @param byteCount [in] Progress bytes count + */ + static void callbackSENDProgress(void* callbackContext, unsigned long byteCount); + + /** Callback function used for receiving DIMSE messages. + * @param callbackContext [in] The desired user callback data + * @param byteCount [in] Progress bytes count + */ + static void callbackRECEIVEProgress(void* callbackContext, unsigned long byteCount); private: - - /// Current association run by this SCP - T_ASC_Association *m_assoc; - - /// SCP configuration. The configuration is a shared object since in some scenarios one - /// might like to share a single configuration instance with multiple SCPs without copying - /// it, e.g. in the context of the DcmSCPPool class. - DcmSharedSCPConfig m_cfg; - - /** Drops association and clears internal structures to free memory - */ - void dropAndDestroyAssociation(); - - /** Private undefined copy constructor. Shall never be called. - * @param src Source object - */ - DcmSCP(const DcmSCP &src); - - /** Private undefined assignment operator. Shall never be called. - * @param src Source object - * @return Reference to this - */ - DcmSCP &operator=(const DcmSCP &src); + /// Network instance run by this SCP + T_ASC_Network* m_network; + + /// Current association run by this SCP + T_ASC_Association* m_assoc; + + /// SCP configuration. The configuration is a shared object since in some scenarios one + /// might like to share a single configuration instance with multiple SCPs without copying + /// it, e.g. in the context of the DcmSCPPool class. + DcmSharedSCPConfig m_cfg; + + /** Drops association and clears internal structures to free memory + */ + void dropAndDestroyAssociation(); + + /** Private undefined copy constructor. Shall never be called. + * @param src Source object + */ + DcmSCP(const DcmSCP& src); + + /** Private undefined assignment operator. Shall never be called. + * @param src Source object + * @return Reference to this + */ + DcmSCP& operator=(const DcmSCP& src); }; #endif // SCP_H diff --git a/dcmnet/include/dcmtk/dcmnet/scpcfg.h b/dcmnet/include/dcmtk/dcmnet/scpcfg.h index bce3c364..9d23a078 100644 --- a/dcmnet/include/dcmtk/dcmnet/scpcfg.h +++ b/dcmnet/include/dcmtk/dcmnet/scpcfg.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2012-2017, OFFIS e.V. + * Copyright (C) 2012-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -28,6 +28,8 @@ #include "dcmtk/dcmnet/dimse.h" #include "dcmtk/ofstd/ofmem.h" /* For OFshared_ptr */ +class DcmTransportLayer; + /** Class that encapsulates an SCP configuration that is needed in order to * configure the service negotiation behavior (presentation contexts, AE * title, listening port, etc) as well as some runtime configuration like @@ -296,6 +298,23 @@ public: */ OFBool getProgressNotificationMode() const; + /** Returns true if an external transport layer (e.g. TLS) is enabled, + * false if the default, transparent layer is used. + * @return true if an external transport layer is enabled + */ + OFBool transportLayerEnabled() const; + + /** Returns pointer to the transport layer object in use + * @return pointer to the transport layer object in use, may be NULL. + */ + DcmTransportLayer * getTransportLayer() const; + + /** set an explicit transport layer (e.g. for TLS communication) to use + * @param tlayer [in] The transport layer object. + * This function does not take ownership of tlayer. + */ + void setTransportLayer(DcmTransportLayer *tlayer); + /** Dump presentation contexts to given output stream, useful for debugging. * @param out [out] The output stream * @param profileName [in] The profile to dump. If empty (default), the currently @@ -393,6 +412,10 @@ protected: /// Progress notification mode (default: OFTrue) OFBool m_progressNotificationMode; + + /// The transport layer in use for communication (e.g. for TLS). + /// Default is NULL for the normal TCP layer. + DcmTransportLayer *m_tLayer; /// Doesn't have ownership }; /** Enables sharing configurations by multiple DcmSCPs. diff --git a/dcmnet/include/dcmtk/dcmnet/scu.h b/dcmnet/include/dcmtk/dcmnet/scu.h index 815f2545..68924dd3 100644 --- a/dcmnet/include/dcmtk/dcmnet/scu.h +++ b/dcmnet/include/dcmtk/dcmnet/scu.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2008-2017, OFFIS e.V. + * Copyright (C) 2008-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -22,166 +22,168 @@ #ifndef SCU_H #define SCU_H -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/dcmdata/dctk.h" /* covers most common dcmdata classes */ +#include "dcmtk/dcmdata/dctk.h" /* covers most common dcmdata classes */ +#include "dcmtk/dcmnet/dcasccff.h" /* for reading a association config file */ +#include "dcmtk/dcmnet/dcasccfg.h" /* for holding association config file infos */ #include "dcmtk/dcmnet/dcompat.h" -#include "dcmtk/dcmnet/dimse.h" /* DIMSE network layer */ -#include "dcmtk/dcmnet/dcasccff.h" /* for reading a association config file */ -#include "dcmtk/dcmnet/dcasccfg.h" /* for holding association config file infos */ +#include "dcmtk/dcmnet/dimse.h" /* DIMSE network layer */ #include "dcmtk/ofstd/oflist.h" - // include this file in doxygen documentation /** @file scu.h * @brief general Service Class User (SCU) class */ - /** Different types of closing an association */ enum DcmCloseAssociationType { - /// Release the current association - DCMSCU_RELEASE_ASSOCIATION, - /// Abort the current association - DCMSCU_ABORT_ASSOCIATION, - /// Peer requested release (Aborting) - DCMSCU_PEER_REQUESTED_RELEASE, - /// Peer aborted the association - DCMSCU_PEER_ABORTED_ASSOCIATION + /// Release the current association + DCMSCU_RELEASE_ASSOCIATION, + /// Abort the current association + DCMSCU_ABORT_ASSOCIATION, + /// Peer requested release (Aborting) + DCMSCU_PEER_REQUESTED_RELEASE, + /// Peer aborted the association + DCMSCU_PEER_ABORTED_ASSOCIATION }; /** Storage mode used for DICOM objects received via C-STORE */ enum DcmStorageMode { - /// Ignore any objects received via C-STORE - DCMSCU_STORAGE_IGNORE, - /// Try to store the objects to disk - DCMSCU_STORAGE_DISK, - /// Try to store to disk in bit-preserving mode. This is especially useful - /// for huge files that cannot fully be received in memory since the data - /// is directly streamed to disk. Originally, this was introduced for DICOM - /// signatures which can be kept valid this way. - DCMSCU_STORAGE_BIT_PRESERVING + /// Ignore any objects received via C-STORE + DCMSCU_STORAGE_IGNORE, + /// Try to store the objects to disk + DCMSCU_STORAGE_DISK, + /// Try to store to disk in bit-preserving mode. This is especially useful + /// for huge files that cannot fully be received in memory since the data + /// is directly streamed to disk. Originally, this was introduced for DICOM + /// signatures which can be kept valid this way. + DCMSCU_STORAGE_BIT_PRESERVING }; - /** Base class for C-FIND, C-MOVE and C-GET responses */ class DCMTK_DCMNET_EXPORT QRResponse { - public: - - /** Standard constructor. - */ - QRResponse() : - m_messageIDRespondedTo(0), - m_affectedSOPClassUID(), - m_dataset(NULL), - m_status(0), - m_statusDetail(NULL) {} - - /** Destructor, cleans up internal memory (dataset if present). - */ - virtual ~QRResponse() { delete m_dataset; delete m_statusDetail; } - - /// The message ID responded to (mandatory response field, - /// equals message ID from request) - Uint16 m_messageIDRespondedTo; - - /// Optional response field according to part 7 of the standard. - /// If present, equals SOP Class UID from request. - OFString m_affectedSOPClassUID; - - /// Conditional response field (NULL if absent). From the standard (2009, - /// part 4, C.4.2.1.4.2), for C-MOVE: In Q/R if no C-STORE sub-operation - /// failed, Failed SOP Instance UID List (0008,0058) is absent and - /// therefore no Data Set shall be sent in the C-MOVE response. Further - /// rules: Statuses of Canceled, Failure, Refused, or Warning shall - /// contain the Failed SOP Instance UID List Attribute; status of - /// Pending shall not. - DcmDataset *m_dataset; - - /// The returned DIMSE status (mandatory Response Field) - Uint16 m_status; - - /// Status detail (NULL if absent). For some DIMSE return status codes, - /// an additional dataset is sent which gives further information (i.e. - /// in case of warnings or errors). - DcmDataset *m_statusDetail; +public: + /** Standard constructor. + */ + QRResponse() + : m_messageIDRespondedTo(0) + , m_affectedSOPClassUID() + , m_dataset(NULL) + , m_status(0) + , m_statusDetail(NULL) + { + } -private: + /** Destructor, cleans up internal memory (dataset if present). + */ + virtual ~QRResponse() + { + delete m_dataset; + delete m_statusDetail; + } - /** Private undefined copy constructor. - * @param other The find response to copy from - */ - QRResponse(const QRResponse &other); + /// The message ID responded to (mandatory response field, + /// equals message ID from request) + Uint16 m_messageIDRespondedTo; - /** Private undefined assignment operator. - * @param other The find response that should be assigned from - * @return Reference to this - */ - QRResponse &operator=(const QRResponse &other); -}; + /// Optional response field according to part 7 of the standard. + /// If present, equals SOP Class UID from request. + OFString m_affectedSOPClassUID; + + /// Conditional response field (NULL if absent). From the standard (2009, + /// part 4, C.4.2.1.4.2), for C-MOVE: In Q/R if no C-STORE sub-operation + /// failed, Failed SOP Instance UID List (0008,0058) is absent and + /// therefore no Data Set shall be sent in the C-MOVE response. Further + /// rules: Statuses of Canceled, Failure, Refused, or Warning shall + /// contain the Failed SOP Instance UID List Attribute; status of + /// Pending shall not. + DcmDataset* m_dataset; + + /// The returned DIMSE status (mandatory Response Field) + Uint16 m_status; + + /// Status detail (NULL if absent). For some DIMSE return status codes, + /// an additional dataset is sent which gives further information (i.e. + /// in case of warnings or errors). + DcmDataset* m_statusDetail; + +private: + /** Private undefined copy constructor. + * @param other The find response to copy from + */ + QRResponse(const QRResponse& other); + /** Private undefined assignment operator. + * @param other The find response that should be assigned from + * @return Reference to this + */ + QRResponse& operator=(const QRResponse& other); +}; /// Base class representing for single C-GET or C-MOVE response class DCMTK_DCMNET_EXPORT RetrieveResponse : public QRResponse { public: - /** Standard constructor - */ - RetrieveResponse() : - m_numberOfRemainingSubops(0), - m_numberOfCompletedSubops(0), - m_numberOfFailedSubops(0), - m_numberOfWarningSubops(0) {} - - /** Destructor, cleans up internal memory - */ - virtual ~RetrieveResponse() {} - - /** Prints response to INFO log level. - */ - void print(); - - /// Number of remaining sub operations (in Q/R: C-STORE calls). - /// For Q/R MOVE and GET, for status of pending this field shall be filled. - /// For others, the field may be filled. - Uint16 m_numberOfRemainingSubops; - - /// Number of successfully completed sub operations (in Q/R: C-STORE calls). - /// For Q/R MOVE and GET, for status of pending this field shall be filled. - /// For others, the field may be filled. - Uint16 m_numberOfCompletedSubops; - - /// Number of failed sub operations (in Q/R: C-STORE calls). - /// For Q/R MOVE and GET, for status of pending this field shall be filled. - /// For others, the field may be filled. - Uint16 m_numberOfFailedSubops; - - /// Number generated warnings generated by sub operations (in Q/R: C-STORE calls). - /// For Q/R MOVE and GET, for status of pending this field shall be filled. - /// For others, the field may be filled. - Uint16 m_numberOfWarningSubops; + /** Standard constructor + */ + RetrieveResponse() + : m_numberOfRemainingSubops(0) + , m_numberOfCompletedSubops(0) + , m_numberOfFailedSubops(0) + , m_numberOfWarningSubops(0) + { + } -private: + /** Destructor, cleans up internal memory + */ + virtual ~RetrieveResponse() + { + } - /** Private undefined copy constructor - * @param other Response to copy from - */ - RetrieveResponse(const RetrieveResponse &other); + /** Prints response to INFO log level. + */ + void print(); - /** Private undefined assignment operator - * @param other Response that should be assigned from - * @return Reference to this - */ - RetrieveResponse &operator=(const RetrieveResponse &other); -}; + /// Number of remaining sub operations (in Q/R: C-STORE calls). + /// For Q/R MOVE and GET, for status of pending this field shall be filled. + /// For others, the field may be filled. + Uint16 m_numberOfRemainingSubops; + + /// Number of successfully completed sub operations (in Q/R: C-STORE calls). + /// For Q/R MOVE and GET, for status of pending this field shall be filled. + /// For others, the field may be filled. + Uint16 m_numberOfCompletedSubops; + /// Number of failed sub operations (in Q/R: C-STORE calls). + /// For Q/R MOVE and GET, for status of pending this field shall be filled. + /// For others, the field may be filled. + Uint16 m_numberOfFailedSubops; + + /// Number generated warnings generated by sub operations (in Q/R: C-STORE calls). + /// For Q/R MOVE and GET, for status of pending this field shall be filled. + /// For others, the field may be filled. + Uint16 m_numberOfWarningSubops; + +private: + /** Private undefined copy constructor + * @param other Response to copy from + */ + RetrieveResponse(const RetrieveResponse& other); + + /** Private undefined assignment operator + * @param other Response that should be assigned from + * @return Reference to this + */ + RetrieveResponse& operator=(const RetrieveResponse& other); +}; /** Base class for implementing DICOM Service Class User functionality. The class offers * support for negotiating associations and sending and receiving arbitrary DIMSE messages @@ -193,885 +195,884 @@ class DCMTK_DCMNET_EXPORT DcmSCU { public: + /** Constructor, just initializes internal class members + */ + DcmSCU(); - /** Constructor, just initializes internal class members - */ - DcmSCU(); - - /** Virtual destructor - */ - virtual ~DcmSCU(); - - /** Add presentation context to be used for association negotiation - * @param abstractSyntax [in] Abstract syntax name in UID format - * @param xferSyntaxes [in] List of transfer syntaxes to be added for the given abstract - * syntax - * @param role [in] The role to be negotiated - * @return EC_Normal if adding was successful, otherwise error code - */ - OFCondition addPresentationContext(const OFString &abstractSyntax, - const OFList &xferSyntaxes, - const T_ASC_SC_ROLE role = ASC_SC_ROLE_DEFAULT); - - /** Initialize network, i.e.\ prepare for association negotiation. If the SCU is already - * connected, the call will not be successful and the old connection keeps open. - * @return EC_Normal if initialization was successful, otherwise error code. - * NET_EC_AlreadyConnected if SCU is already connected. - */ - virtual OFCondition initNetwork(); - - /** Negotiate association by using presentation contexts and parameters as defined by - * earlier function calls. If negotiation fails, there is no need to close the association - * or to do anything else with this class. - * @return EC_Normal if negotiation was successful, otherwise error code. - * NET_EC_AlreadyConnected if SCU is already connected. - */ - virtual OFCondition negotiateAssociation(); - - /** After negotiation association, this call returns the first usable presentation context - * given the desired abstract syntax and transfer syntax - * @param abstractSyntax [in] The abstract syntax (UID) to look for - * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer - * syntax is not checked. - * @param requestorRole [in] The role to look for (denoting the role the association - * requestor plays) - * @return Adequate Presentation context ID that can be used. 0 if none found. - */ - T_ASC_PresentationContextID findPresentationContextID(const OFString &abstractSyntax, - const OFString &transferSyntax, - const T_ASC_SC_ROLE requestorRole = ASC_SC_ROLE_DEFAULT); - - /** After a successful association negotiation, this function is called to return the - * presentation context ID that best matches the desired abstract syntax and transfer - * syntax (TS). The function tries to do the following: - * - If possible finds a presentation context with matching TS - * - Else then tries to find an explicit VR uncompressed TS presentation context - * - Else then tries to find an implicit VR uncompressed TS presentation context - * - Else finally accepts each matching presentation ctx independent of TS. - * @warning This method does not support filtering for a specific role, yet. - * @param abstractSyntax [in] The abstract syntax (UID) to look for - * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer - * syntax is not checked. - * @return Adequate Presentation context ID that can be used. 0 if no appropriate - * presentation context could be found at all. - */ - T_ASC_PresentationContextID findAnyPresentationContextID(const OFString &abstractSyntax, - const OFString &transferSyntax); - - /** This function sends a C-ECHO command via network to another DICOM application - * @param presID [in] Presentation context ID to use. A value of 0 lets SCP class tries - * to choose one on its own. - * @return EC_Normal if echo was successful, an error code otherwise - * - */ - virtual OFCondition sendECHORequest(const T_ASC_PresentationContextID presID); - - /** This function sends a C-STORE request on the currently opened association and receives - * the corresponding response then. If required and supported, the dataset of the SOP - * instance can be converted automatically to the network transfer syntax that was - * negotiated (and is specified by the parameter 'presID'). However, this feature is - * disabled by default. See setDatasetConversionMode() on how to enable it. - * @param presID [in] Contains in the end the ID of the presentation context which - * was specified in the DIMSE command. If 0 is given, the - * function tries to find an appropriate presentation context - * itself (based on SOP class and original transfer syntax of - * the 'dicomFile' or 'dataset'). - * @param dicomFile [in] The filename of the DICOM file to be sent. Alternatively, a - * dataset can be given in the next parameter. If both are given - * the dataset from the file name is used. - * @param dataset [in] The dataset to be sent. Alternatively, a filename can be - * specified in the previous parameter. If both are given the - * dataset from the filename is used. - * @param rspStatusCode [out] The response status code received. 0 means success, others - * can be found in the DICOM standard. - * @param moveOriginatorAETitle [in] If this C-STORE is started due to a C-MOVE request, - * this parameter informs the C-STORE SCP about the C-MOVE - * client's AE title. - * @param moveOriginatorMsgID [in] If this C-STORE is started due to a C-MOVE request, - * this parameter informs the C-STORE SCP about the C-MOVE - * message ID. - * @return EC_Normal if request could be issued and response was received successfully, - * error code otherwise. That means that if the receiver sends a response denoting - * failure of the storage request, EC_Normal will be returned. - */ - virtual OFCondition sendSTORERequest(const T_ASC_PresentationContextID presID, - const OFFilename &dicomFile, - DcmDataset *dataset, - Uint16 &rspStatusCode, - const OFString &moveOriginatorAETitle = "", - const Uint16 moveOriginatorMsgID = 0); - - /** Sends a C-MOVE Request on given presentation context and receives list of responses. - * The function receives the first response and then calls the function handleMOVEResponse() - * which gets the relevant presentation context together with the response dataset and - * status information. Then it waits again for the next response, if there are more to - * come (i.e. response status is PENDING). In the end, after receiving all responses, the - * full list of responses is returned to the caller. If he is not interested, he just sets - * responses=NULL when calling the function. - * This function can be overwritten by actual SCU implementations but just should work fine - * for most people. - * @param presID [in] The presentation context ID that should be used. - * Must be an odd number. - * @param moveDestinationAETitle [in] The move destination's AE title, i.e.\ the one that - * is used for connection to the storage server. - * @param dataset [in] The dataset containing the information about the - * object(s) to be retrieved. - * @param responses [out] The incoming C-MOVE responses for this request. - * The caller is responsible for providing a non-NULL - * pointer for this case. After receiving the results, - * the caller is responsible for freeing the memory of - * this variable. If NULL is specified, the responses - * will not be returned to the caller. - * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses - * (with whatever status) could be received. - */ - virtual OFCondition sendMOVERequest(const T_ASC_PresentationContextID presID, - const OFString &moveDestinationAETitle, - DcmDataset *dataset, - OFList *responses); - - /** This is the standard handler for C-MOVE message responses: It just adds up all responses - * it receives and prints a DEBUG message. Therefore, it is called for each response - * received in sendMOVERequest(). The idea is of course to overwrite this function in a - * derived, actual SCU implementation if required. Thus, after each response, the caller of - * sendMOVERequest() can decide on its own whether he wants to cancel the C-MOVE session, - * terminate the association, do something useful or whatever. Thus this function is a more - * object-oriented kind of callback. - * @param presID [in] The presentation context ID where the response was - * received on. - * @param response [in] The C-MOVE response received. - * @param waitForNextResponse [out] Denotes whether SCU should try to receive another - * response. If set to OFTrue, then sendMOVERequest() will - * continue waiting for responses. The current - * implementation does that for all responses do not have - * status Failed, Warning, Success or unknown. If set to - * OFFalse, sendMOVERequest() will return control to the - * caller. - * @return EC_Normal, if response could be handled. Error code otherwise. - * The current implementation always returns EC_Normal. - */ - virtual OFCondition handleMOVEResponse(const T_ASC_PresentationContextID presID, - RetrieveResponse *response, - OFBool &waitForNextResponse); - - /** Sends a C-GET Request on given presentation context and receives list of responses. It - * then switches control to the function handleCGETSession(). - * The full list of responses is returned to the caller. If he is not interested, he can - * set responses=NULL when calling the function. - * This function can be overwritten by actual SCU implementations but just should work fine - * for most people. - * @param presID [in] The presentation context ID that should be used. Must be an odd - * number. - * @param dataset [in] The dataset containing the information about the - * object(s) to be retrieved - * @param responses [out] The incoming C-GET responses for this request. If the caller - * specifies NULL, no responses will be returned; otherwise there - * should be at least one final C-GET response (mandatory). C-GET - * responses after each DICOM object received are optional and may - * have been omitted by the server. - * @return EC_Normal if everything went fine, i.e.\ if request could be sent and expected - * responses (with whatever status) could be received. - */ - virtual OFCondition sendCGETRequest(const T_ASC_PresentationContextID presID, - DcmDataset *dataset, - OFList *responses); - - /** Does the logic for switching between C-GET Response and C-STORE Requests. Sends a C-GET - * Request on given presentation context and receives list of responses. The full list of - * responses is returned to the caller. If he is not interested, he can set responses=NULL - * when calling the function. After sending a C-GET Request, there might be two different - * responses coming in: C-GET-RSP (optional after each received object and mandatory after - * the last object) or a mandatory C-STORE for each incoming object that is received due to - * the request. This function therefore either calls handleCGETResponse() or - * handleSTORERequest() in order to deal with the incoming message. All other messages lead - * to an error within this handler. - * This function can be overwritten by actual SCU implementations but just should work fine - * for most people. - * @param presID [in] The presentation context ID that should be used. Must be an odd - * number. - * @param dataset [in] The dataset containing the information about the object(s) to be - * retrieved - * @param responses [out] The incoming C-GET responses for this request. If the caller - * specifies NULL, no responses will be returned; otherwise there - * should be at least one final C-GET response (mandatory). C-GET - * responses after each DICOM object received are optional and may - * have been omitted by the server. - * @return EC_Normal if everything went fine, i.e.\ if request could be send - * and expected responses (with whatever status) could be received. - */ - virtual OFCondition handleCGETSession(const T_ASC_PresentationContextID presID, - DcmDataset *dataset, - OFList *responses); - - /** Function handling a single C-GET Response. This standard handler reads the status of the - * response and decides whether to receive any further messages related to the original - * C-GET Request or whether the last response was received or an error occurred. - * @param presID [in] The presentation context the C-GET Response was - * received on. - * @param response [in] The response received - * @param continueCGETSession [out] Defines whether it is decided to wait for further C-GET - * Responses/C-STORE Requests within this C-GET session - * @return If no errors occur (dataset response NULL, SCU not connected), this method will - * return EC_Normal, otherwise error code. - */ - virtual OFCondition handleCGETResponse(const T_ASC_PresentationContextID presID, - RetrieveResponse* response, - OFBool &continueCGETSession); - - /** Function handling a single C-STORE Request. If storage mode is set to disk (default), - * this function is called and the incoming object stored to disk. - * @param presID [in] The presentation context the C-STORE Request was - * received on. - * @param incomingObject [in] The dataset (the object) received. The function - * takes ownership of the dataset, i.e. deletes it - * after processing. - * @param continueCGETSession [out] Defines whether it is decided to wait for further - * C-GET Responses/C-STORE requests within this C-GET - * session. - * @param cStoreReturnStatus [out] Denotes the desired C-STORE return status. - * @return If errors occur (incomingObject NULL or SCU not connected or file could not be - * stored), this method will return an error code otherwise EC_Normal. - */ - virtual OFCondition handleSTORERequest(const T_ASC_PresentationContextID presID, - DcmDataset *incomingObject, - OFBool &continueCGETSession, - Uint16 &cStoreReturnStatus); - - /** Function handling a single C-STORE Request. If storage mode is set to bit preserving, - * this function is called and the incoming object stored directly to disk, i.e. not stored - * fully in memory. - * @param presID [in] The presentation context the C-STORE Response was received on. - * @param filename [in] The filename to store to - * @param request [in] The incoming C-STORE request command set - * @return If errors occur (incomingObject NULL or SCU not connected filename not - * specified), this method will return an error code otherwise EC_Normal. - */ - virtual OFCondition handleSTORERequestFile(T_ASC_PresentationContextID *presID, - const OFString &filename, - T_DIMSE_C_StoreRQ *request); - - /** Sends a C-FIND Request on given presentation context and receives list of responses. - * The function receives the first response and then calls the function handleFINDResponse() - * which gets the relevant presentation context together with the response dataset and - * status information. Then it waits again for the next response, if there are more to - * come (i.e. response status is PENDING). In the end, after receiving all responses, the - * full list of responses is returned to the caller. If he is not interested, he just sets - * responses=NULL when calling the function. - * This function can be overwritten by actual SCU implementations but just should work fine - * for most people. - * @param presID [in] The presentation context ID that should be used. Must be an odd - * number. - * @param queryKeys [in] The dataset containing the query keys to be searched for on the - * server (SCP). - * @param responses [out] The incoming C-FIND responses for this request. The caller is - * responsible for providing a non-NULL pointer for this case. - * After receiving the results, the caller is responsible for - * freeing the memory of this variable. If NULL is specified, the - * responses will be not returned to the caller. - * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses - * (with whatever status) could be received. - */ - virtual OFCondition sendFINDRequest(const T_ASC_PresentationContextID presID, - DcmDataset *queryKeys, - OFList *responses); - - /** This is the standard handler for C-FIND message responses: It just adds up all responses - * it receives and prints a DEBUG message. Therefore, it is called for each response - * received in sendFINDRequest(). The idea is of course to overwrite this function in a - * derived, actual SCU implementation if required. Thus, after each response, the caller of - * sendFINDRequest() can decide on its own whether he wants to cancel the C-FIND session, - * terminate the association, do something useful or whatever. That way this is a more - * object-oriented kind of callback. - * @param presID [in] The presentation context ID where the response was - * received on. - * @param response [in] The C-FIND response received. - * @param waitForNextResponse [out] Denotes whether SCU should try to receive another - * response. If set to OFTrue, then sendFINDRequest() - * will continue waiting for responses. The current - * implementation does that for all responses do not have - * status SUCESSS. If set to OFFalse, sendFINDRequest() - * will return control to the caller. - * @return EC_Normal, if response could be handled. Error code otherwise. - * The current implementation always returns EC_Normal. - */ - virtual OFCondition handleFINDResponse(const T_ASC_PresentationContextID presID, - QRResponse *response, - OFBool &waitForNextResponse); - - /** Send C-CANCEL and, therefore, ends the C-FIND -GET or -MOVE session, i.e.\ no further - * responses will be handled. A call to this function only makes sense if an association - * is open, the given presentation context represents a valid C-FIND/GET/MOVE-enabled SOP - * class and usually only, if the last command send on that presentation context was a - * C-FIND message. - * @param presID [in] The presentation context ID where the C-CANCEL should be sent on. - * @return The current implementation always returns EC_Normal. - */ - virtual OFCondition sendCANCELRequest(const T_ASC_PresentationContextID presID); - - /** This function sends a N-ACTION request on the currently opened association and receives - * the corresponding response then - * @param presID [in] The ID of the presentation context to be used for sending - * the request message. Should not be 0. - * @param sopInstanceUID [in] The requested SOP Instance UID - * @param actionTypeID [in] The action type ID to be used - * @param reqDataset [in] The dataset to be sent - * @param rspStatusCode [out] The response status code received. 0 means success, - * others can be found in the DICOM standard. - * @return EC_Normal if request could be issued and response was received successfully, - * an error code otherwise - */ - virtual OFCondition sendACTIONRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, - const Uint16 actionTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode); - - /** This function sends N-EVENT-REPORT request and receives the corresponding response - * @param presID [in] The ID of the presentation context to be used for sending - * the request message. Should not be 0. - * @param sopInstanceUID [in] The requested SOP Instance UID - * @param eventTypeID [in] The event type ID to be used - * @param reqDataset [in] The request dataset to be sent - * @param rspStatusCode [out] The response status code received. 0 means success, - * others can be found in the DICOM standard. - * @return EC_Normal if request could be issued and response was received successfully, - * an error code otherwise - */ - virtual OFCondition sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, - const Uint16 eventTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode); - - /** Receives N-EVENT-REPORT request on the currently opened association and sends a - * corresponding response. Calls checkEVENTREPORTRequest() in order to determine the - * DIMSE status code to be used for the N-EVENT-REPORT response. - * @param reqDataset [out] Pointer to the dataset received - * @param eventTypeID [out] Event Type ID from the command set received - * @param timeout [in] Optional timeout in seconds for receiving data. This value - * (if not 0) overwrites the standard DIMSE timeout and also - * enables the non-blocking mode for receiving the request. - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition handleEVENTREPORTRequest(DcmDataset *&reqDataset, - Uint16 &eventTypeID, - const int timeout = 0); - - /** Closes the association created by this SCU. Also resets the current association. - * @deprecated The use of this method is deprecated. Please use releaseAssociation() - * or abortAssociation() instead. - * @param closeType [in] Define whether to release or abort the association - */ - virtual void closeAssociation(const DcmCloseAssociationType closeType); - - /** Releases the current association by sending an A-RELEASE request to the SCP. - * Please note that this release only applies to associations that have been - * created by calling initNetwork() and negotiateAssociation(). - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition releaseAssociation(); - - /** Aborts the current association by sending an A-ABORT request to the SCP. - * Please note that this abort only applies to associations that have been - * created by calling initNetwork() and negotiateAssociation(). - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition abortAssociation(); - - /* Set methods */ - - /** Set maximum PDU length (to be received by SCU) - * @param maxRecPDU [in] The maximum PDU size to use in bytes - */ - void setMaxReceivePDULength(const Uint32 maxRecPDU); - - /** Set whether to send in DIMSE blocking or non-blocking mode - * @param blockingMode [in] Either blocking or non-blocking mode - */ - void setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode); - - /** Set SCU's AE title to be used in association negotiation - * @param myAETtitle [in] The SCU's AE title to be used - */ - void setAETitle(const OFString &myAETtitle); - - /** Set SCP's host (host name or IP address) to talk to in association negotiation - * @param peerHostName [in] The SCP's hostname or IP address to be used - */ - void setPeerHostName(const OFString &peerHostName); - - /** Set SCP's AE title to talk to in association negotiation - * @param peerAETitle [in] The SCP's AE title to be used - */ - void setPeerAETitle(const OFString &peerAETitle); - - /** Set SCP's port number to connect to for association negotiation - * @param peerPort [in] The SCP's port number - */ - void setPeerPort(const Uint16 peerPort); - - /** Set timeout for receiving DIMSE messages - * @param dimseTimeout [in] DIMSE timeout in seconds for receiving data. - * If the blocking mode is DIMSE_NONBLOCKING the SCU - * will try to read data from the incoming socket stream - * for the number of seconds configured. - */ - void setDIMSETimeout(const Uint32 dimseTimeout); - - /** Set timeout for receiving ACSE messages - * @param acseTimeout [in] ACSE timeout in seconds used by timer for message timeouts - * during association negotiation - */ - void setACSETimeout(const Uint32 acseTimeout); - - /** Set global timeout for connecting to the SCP. Note that this is a global - * DCMTK setting i.e. it affects all code that uses dcmnet to start a DICOM - * association to another host. Setting the timeout to -1 sets an infinite timeout, - * i.e. any association request will wait forever (blocking) until the SCP accepts - * the connection request. A value of 0 lets the SCU return immediately if the SCP - * is not reachable at the first attempt. - * @param connectionTimeout [in] Connection Timeout in seconds when connecting - * to SCPs. -1 will wait forever (blocking mode). - */ - void setConnectionTimeout(const Sint32 connectionTimeout); - - - /** Set an association configuration file and profile to be used - * @param filename [in] File name of the association configuration file - * @param profile [in] Profile inside the association negotiation file - */ - void setAssocConfigFileAndProfile(const OFString &filename, - const OFString &profile); - - /** Set the directory that should be used by the standard C-GET handler to store objects - * that come in with the corresponding C-STORE requests - * @param storeDir [in] The directory to store to. It is checked in handleSTORERequest() - * whether the directory is writeable and readable. By default, the - * received objects are stored in the current working directory. - */ - void setStorageDir(const OFString &storeDir); - - /** Set the storage mode to be used. Default is DCMSCU_STORAGE_DISK. - * @param storageMode The storage mode to be used. - */ - void setStorageMode(const DcmStorageMode storageMode); - - /** Set whether to show presentation contexts in verbose or debug mode - * @param mode [in] Show presentation contexts in verbose mode if OFTrue. By default, - * the presentation contexts are shown in debug mode. - */ - void setVerbosePCMode(const OFBool mode); - - /** Set the mode that specifies whether the transfer syntax of the dataset can be changed - * for network transmission. This mainly covers the compression/decompression of datasets, - * which is disabled by default. - * @param mode [in] Allow dataset conversion if OFTrue - */ - void setDatasetConversionMode(const OFBool mode); - - /** Set the mode that specifies whether the progress of sending and receiving DIMSE - * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), - * respectively. The progress notification is enabled by default. - * @param mode [in] Disable progress notification if OFFalse - */ - void setProgressNotificationMode(const OFBool mode); - - /* Get methods */ - - /** Get current connection status - * @return OFTrue if SCU is currently connected, OFFalse otherwise - */ - OFBool isConnected() const; - - /** Returns maximum PDU length configured to be received by SCU - * @return Maximum PDU length in bytes - */ - Uint32 getMaxReceivePDULength() const; - - /** Returns whether DIMSE messaging is configured to be blocking or unblocking - * @return The blocking mode configured - */ - T_DIMSE_BlockingMode getDIMSEBlockingMode() const; - - /** Returns the SCU's own configured AE title - * @return The AE title configured for this SCU - */ - const OFString &getAETitle() const; - - /** Returns the SCP's (peer's) host configured - * @return The host name (or IP) configured to be talked to - */ - const OFString &getPeerHostName() const; - - /** Returns the SCP's (peer's) AE title configured - * @return The AE title configured to be talked to - */ - const OFString &getPeerAETitle() const; - - /** Returns the SCP's (peer's) TCP/IP port configured - * @return The port configured to talked to - */ - Uint16 getPeerPort() const; - - /** Returns DIMSE timeout in seconds for receiving data. If the blocking - * mode is DIMSE_NONBLOCKING the SCU will try to read data from - * the incoming socket stream for the number of seconds configured. - * @return The DIMSE timeout (in seconds) configured - */ - Uint32 getDIMSETimeout() const; - - /** Returns ACSE timeout in seconds used by timer for message timeouts during - * association negotiation. - * @return The ACSE timeout (in seconds) configured - */ - Uint32 getACSETimeout() const; - - /** Returns the timeout configured defining how long SCU will wait for the - * SCP when requesting an association. -1 means infinite waiting (blocking), - * 0 means no waiting at all. Note that this is currently a global DCMTK setting. - * @return The connection timeout (in seconds) - */ - Sint32 getConnectionTimeout() const; - - /** Returns the storage directory used for storing objects received with C-STORE requests - * in the context of C-GET sessions. Default is empty string which refers to the current - * working directory. - * @return The storage directory - */ - OFString getStorageDir() const; - - /** Returns the storage mode enabled - * @return The storage mode enabled - */ - DcmStorageMode getStorageMode() const; - - /** Returns the verbose presentation context mode configured specifying whether details - * on the presentation contexts (negotiated during association setup) should be shown in - * verbose or debug mode. The latter is the default. - * @return The current verbose presentation context mode. Show details on the - * presentation contexts on INFO log level (verbose) if OFTrue and on DEBUG - * level if OFFalse. - */ - OFBool getVerbosePCMode() const; - - /** Returns the mode that specifies whether the transfer syntax of the dataset can be - * changed for network transmission. This mainly covers the compression/decompression - * of datasets, which is disabled by default. - * @return The current dataset conversion mode, enabled if OFTrue - */ - OFBool getDatasetConversionMode() const; - - /** Returns the mode that specifies whether the progress of sending and receiving DIMSE - * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), - * respectively. The progress notification is enabled by default. - * @return The current progress notification mode, enabled if OFTrue - */ - OFBool getProgressNotificationMode() const; - - /** Returns whether SCU is configured to create a TLS connection with the SCP - * @return OFFalse for this class but may be overridden by derived classes - */ - OFBool getTLSEnabled() const; - - /** Deletes internal networking structures from memory */ - void freeNetwork(); + /** Virtual destructor + */ + virtual ~DcmSCU(); + + /** Add presentation context to be used for association negotiation + * @param abstractSyntax [in] Abstract syntax name in UID format + * @param xferSyntaxes [in] List of transfer syntaxes to be added for the given abstract + * syntax + * @param role [in] The role to be negotiated + * @return EC_Normal if adding was successful, otherwise error code + */ + OFCondition addPresentationContext(const OFString& abstractSyntax, + const OFList& xferSyntaxes, + const T_ASC_SC_ROLE role = ASC_SC_ROLE_DEFAULT); + + /** Initialize network, i.e.\ prepare for association negotiation. If the SCU is already + * connected, the call will not be successful and the old connection keeps open. + * @return EC_Normal if initialization was successful, otherwise error code. + * NET_EC_AlreadyConnected if SCU is already connected. + */ + virtual OFCondition initNetwork(); -protected: + /** Negotiate association by using presentation contexts and parameters as defined by + * earlier function calls. If negotiation fails, there is no need to close the association + * or to do anything else with this class. + * @return EC_Normal if negotiation was successful, otherwise error code. + * NET_EC_AlreadyConnected if SCU is already connected. + */ + virtual OFCondition negotiateAssociation(); + + /** After negotiation association, this call returns the first usable presentation context + * given the desired abstract syntax and transfer syntax + * @param abstractSyntax [in] The abstract syntax (UID) to look for + * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer + * syntax is not checked. + * @param requestorRole [in] The role to look for (denoting the role the association + * requestor plays) + * @return Adequate Presentation context ID that can be used. 0 if none found. + */ + T_ASC_PresentationContextID findPresentationContextID(const OFString& abstractSyntax, + const OFString& transferSyntax, + const T_ASC_SC_ROLE requestorRole = ASC_SC_ROLE_DEFAULT); + + /** After a successful association negotiation, this function is called to return the + * presentation context ID that best matches the desired abstract syntax and transfer + * syntax (TS). The function tries to do the following: + * - If possible finds a presentation context with matching TS + * - Else then tries to find an explicit VR uncompressed TS presentation context + * - Else then tries to find an implicit VR uncompressed TS presentation context + * - Else finally accepts each matching presentation ctx independent of TS. + * @warning This method does not support filtering for a specific role, yet. + * @param abstractSyntax [in] The abstract syntax (UID) to look for + * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer + * syntax is not checked. + * @return Adequate Presentation context ID that can be used. 0 if no appropriate + * presentation context could be found at all. + */ + T_ASC_PresentationContextID findAnyPresentationContextID(const OFString& abstractSyntax, + const OFString& transferSyntax); + + /** This function sends a C-ECHO command via network to another DICOM application + * @param presID [in] Presentation context ID to use. A value of 0 lets SCP class tries + * to choose one on its own. + * @return EC_Normal if echo was successful, an error code otherwise + * + */ + virtual OFCondition sendECHORequest(const T_ASC_PresentationContextID presID); + + /** This function sends a C-STORE request on the currently opened association and receives + * the corresponding response then. If required and supported, the dataset of the SOP + * instance can be converted automatically to the network transfer syntax that was + * negotiated (and is specified by the parameter 'presID'). However, this feature is + * disabled by default. See setDatasetConversionMode() on how to enable it. + * @param presID [in] Contains in the end the ID of the presentation context which + * was specified in the DIMSE command. If 0 is given, the + * function tries to find an appropriate presentation context + * itself (based on SOP class and original transfer syntax of + * the 'dicomFile' or 'dataset'). + * @param dicomFile [in] The filename of the DICOM file to be sent. Alternatively, a + * dataset can be given in the next parameter. If both are given + * the dataset from the file name is used. + * @param dataset [in] The dataset to be sent. Alternatively, a filename can be + * specified in the previous parameter. If both are given the + * dataset from the filename is used. + * @param rspStatusCode [out] The response status code received. 0 means success, others + * can be found in the DICOM standard. + * @param moveOriginatorAETitle [in] If this C-STORE is started due to a C-MOVE request, + * this parameter informs the C-STORE SCP about the C-MOVE + * client's AE title. + * @param moveOriginatorMsgID [in] If this C-STORE is started due to a C-MOVE request, + * this parameter informs the C-STORE SCP about the C-MOVE + * message ID. + * @return EC_Normal if request could be issued and response was received successfully, + * error code otherwise. That means that if the receiver sends a response denoting + * failure of the storage request, EC_Normal will be returned. + */ + virtual OFCondition sendSTORERequest(const T_ASC_PresentationContextID presID, + const OFFilename& dicomFile, + DcmDataset* dataset, + Uint16& rspStatusCode, + const OFString& moveOriginatorAETitle = "", + const Uint16 moveOriginatorMsgID = 0); + + /** Sends a C-MOVE Request on given presentation context and receives list of responses. + * The function receives the first response and then calls the function handleMOVEResponse() + * which gets the relevant presentation context together with the response dataset and + * status information. Then it waits again for the next response, if there are more to + * come (i.e. response status is PENDING). In the end, after receiving all responses, the + * full list of responses is returned to the caller. If he is not interested, he just sets + * responses=NULL when calling the function. + * This function can be overwritten by actual SCU implementations but just should work fine + * for most people. + * @param presID [in] The presentation context ID that should be used. + * Must be an odd number. + * @param moveDestinationAETitle [in] The move destination's AE title, i.e.\ the one that + * is used for connection to the storage server. + * @param dataset [in] The dataset containing the information about the + * object(s) to be retrieved. + * @param responses [out] The incoming C-MOVE responses for this request. + * The caller is responsible for providing a non-NULL + * pointer for this case. After receiving the results, + * the caller is responsible for freeing the memory of + * this variable. If NULL is specified, the responses + * will not be returned to the caller. + * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses + * (with whatever status) could be received. + */ + virtual OFCondition sendMOVERequest(const T_ASC_PresentationContextID presID, + const OFString& moveDestinationAETitle, + DcmDataset* dataset, + OFList* responses); + + /** This is the standard handler for C-MOVE message responses: It just adds up all responses + * it receives and prints a DEBUG message. Therefore, it is called for each response + * received in sendMOVERequest(). The idea is of course to overwrite this function in a + * derived, actual SCU implementation if required. Thus, after each response, the caller of + * sendMOVERequest() can decide on its own whether he wants to cancel the C-MOVE session, + * terminate the association, do something useful or whatever. Thus this function is a more + * object-oriented kind of callback. + * @param presID [in] The presentation context ID where the response was + * received on. + * @param response [in] The C-MOVE response received. + * @param waitForNextResponse [out] Denotes whether SCU should try to receive another + * response. If set to OFTrue, then sendMOVERequest() will + * continue waiting for responses. The current + * implementation does that for all responses do not have + * status Failed, Warning, Success or unknown. If set to + * OFFalse, sendMOVERequest() will return control to the + * caller. + * @return EC_Normal, if response could be handled. Error code otherwise. + * The current implementation always returns EC_Normal. + */ + virtual OFCondition handleMOVEResponse(const T_ASC_PresentationContextID presID, + RetrieveResponse* response, + OFBool& waitForNextResponse); + + /** Sends a C-GET Request on given presentation context and receives list of responses. It + * then switches control to the function handleCGETSession(). + * The full list of responses is returned to the caller. If he is not interested, he can + * set responses=NULL when calling the function. + * This function can be overwritten by actual SCU implementations but just should work fine + * for most people. + * @param presID [in] The presentation context ID that should be used. Must be an odd + * number. + * @param dataset [in] The dataset containing the information about the + * object(s) to be retrieved + * @param responses [out] The incoming C-GET responses for this request. If the caller + * specifies NULL, no responses will be returned; otherwise there + * should be at least one final C-GET response (mandatory). C-GET + * responses after each DICOM object received are optional and may + * have been omitted by the server. + * @return EC_Normal if everything went fine, i.e.\ if request could be sent and expected + * responses (with whatever status) could be received. + */ + virtual OFCondition sendCGETRequest(const T_ASC_PresentationContextID presID, + DcmDataset* dataset, + OFList* responses); + + /** Does the logic for switching between C-GET Response and C-STORE Requests. Sends a C-GET + * Request on given presentation context and receives list of responses. The full list of + * responses is returned to the caller. If he is not interested, he can set responses=NULL + * when calling the function. After sending a C-GET Request, there might be two different + * responses coming in: C-GET-RSP (optional after each received object and mandatory after + * the last object) or a mandatory C-STORE for each incoming object that is received due to + * the request. This function therefore either calls handleCGETResponse() or + * handleSTORERequest() in order to deal with the incoming message. All other messages lead + * to an error within this handler. + * This function can be overwritten by actual SCU implementations but just should work fine + * for most people. + * @param presID [in] The presentation context ID that should be used. Must be an odd + * number. + * @param dataset [in] The dataset containing the information about the object(s) to be + * retrieved + * @param responses [out] The incoming C-GET responses for this request. If the caller + * specifies NULL, no responses will be returned; otherwise there + * should be at least one final C-GET response (mandatory). C-GET + * responses after each DICOM object received are optional and may + * have been omitted by the server. + * @return EC_Normal if everything went fine, i.e.\ if request could be send + * and expected responses (with whatever status) could be received. + */ + virtual OFCondition handleCGETSession(const T_ASC_PresentationContextID presID, + DcmDataset* dataset, + OFList* responses); + + /** Function handling a single C-GET Response. This standard handler reads the status of the + * response and decides whether to receive any further messages related to the original + * C-GET Request or whether the last response was received or an error occurred. + * @param presID [in] The presentation context the C-GET Response was + * received on. + * @param response [in] The response received + * @param continueCGETSession [out] Defines whether it is decided to wait for further C-GET + * Responses/C-STORE Requests within this C-GET session + * @return If no errors occur (dataset response NULL, SCU not connected), this method will + * return EC_Normal, otherwise error code. + */ + virtual OFCondition handleCGETResponse(const T_ASC_PresentationContextID presID, + RetrieveResponse* response, + OFBool& continueCGETSession); + + /** Function handling a single C-STORE Request. If storage mode is set to disk (default), + * this function is called and the incoming object stored to disk. + * @param presID [in] The presentation context the C-STORE Request was + * received on. + * @param incomingObject [in] The dataset (the object) received. The function + * takes ownership of the dataset, i.e. deletes it + * after processing. + * @param continueCGETSession [out] Defines whether it is decided to wait for further + * C-GET Responses/C-STORE requests within this C-GET + * session. + * @param cStoreReturnStatus [out] Denotes the desired C-STORE return status. + * @return If errors occur (incomingObject NULL or SCU not connected or file could not be + * stored), this method will return an error code otherwise EC_Normal. + */ + virtual OFCondition handleSTORERequest(const T_ASC_PresentationContextID presID, + DcmDataset* incomingObject, + OFBool& continueCGETSession, + Uint16& cStoreReturnStatus); + + /** Function handling a single C-STORE Request. If storage mode is set to bit preserving, + * this function is called and the incoming object stored directly to disk, i.e. not stored + * fully in memory. + * @param presID [in] The presentation context the C-STORE Response was received on. + * @param filename [in] The filename to store to + * @param request [in] The incoming C-STORE request command set + * @return If errors occur (incomingObject NULL or SCU not connected filename not + * specified), this method will return an error code otherwise EC_Normal. + */ + virtual OFCondition + handleSTORERequestFile(T_ASC_PresentationContextID* presID, const OFString& filename, T_DIMSE_C_StoreRQ* request); + + /** Sends a C-FIND Request on given presentation context and receives list of responses. + * The function receives the first response and then calls the function handleFINDResponse() + * which gets the relevant presentation context together with the response dataset and + * status information. Then it waits again for the next response, if there are more to + * come (i.e. response status is PENDING). In the end, after receiving all responses, the + * full list of responses is returned to the caller. If he is not interested, he just sets + * responses=NULL when calling the function. + * This function can be overwritten by actual SCU implementations but just should work fine + * for most people. + * @param presID [in] The presentation context ID that should be used. Must be an odd + * number. + * @param queryKeys [in] The dataset containing the query keys to be searched for on the + * server (SCP). + * @param responses [out] The incoming C-FIND responses for this request. The caller is + * responsible for providing a non-NULL pointer for this case. + * After receiving the results, the caller is responsible for + * freeing the memory of this variable. If NULL is specified, the + * responses will be not returned to the caller. + * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses + * (with whatever status) could be received. + */ + virtual OFCondition + sendFINDRequest(const T_ASC_PresentationContextID presID, DcmDataset* queryKeys, OFList* responses); + + /** This is the standard handler for C-FIND message responses: It just adds up all responses + * it receives and prints a DEBUG message. Therefore, it is called for each response + * received in sendFINDRequest(). The idea is of course to overwrite this function in a + * derived, actual SCU implementation if required. Thus, after each response, the caller of + * sendFINDRequest() can decide on its own whether he wants to cancel the C-FIND session, + * terminate the association, do something useful or whatever. That way this is a more + * object-oriented kind of callback. + * @param presID [in] The presentation context ID where the response was + * received on. + * @param response [in] The C-FIND response received. + * @param waitForNextResponse [out] Denotes whether SCU should try to receive another + * response. If set to OFTrue, then sendFINDRequest() + * will continue waiting for responses. The current + * implementation does that for all responses do not have + * status SUCCESS. If set to OFFalse, sendFINDRequest() + * will return control to the caller. + * @return EC_Normal, if response could be handled. Error code otherwise. + * The current implementation always returns EC_Normal. + */ + virtual OFCondition + handleFINDResponse(const T_ASC_PresentationContextID presID, QRResponse* response, OFBool& waitForNextResponse); + + /** Send C-CANCEL and, therefore, ends the C-FIND -GET or -MOVE session, i.e.\ no further + * responses will be handled. A call to this function only makes sense if an association + * is open, the given presentation context represents a valid C-FIND/GET/MOVE-enabled SOP + * class and usually only, if the last command send on that presentation context was a + * C-FIND message. + * @param presID [in] The presentation context ID where the C-CANCEL should be sent on. + * @return The current implementation always returns EC_Normal. + */ + virtual OFCondition sendCANCELRequest(const T_ASC_PresentationContextID presID); + + /** This function sends a N-ACTION request on the currently opened association and receives + * the corresponding response then + * @param presID [in] The ID of the presentation context to be used for sending + * the request message. Should not be 0. + * @param sopInstanceUID [in] The requested SOP Instance UID + * @param actionTypeID [in] The action type ID to be used + * @param reqDataset [in] The dataset to be sent + * @param rspStatusCode [out] The response status code received. 0 means success, + * others can be found in the DICOM standard. + * @return EC_Normal if request could be issued and response was received successfully, + * an error code otherwise + */ + virtual OFCondition sendACTIONRequest(const T_ASC_PresentationContextID presID, + const OFString& sopInstanceUID, + const Uint16 actionTypeID, + DcmDataset* reqDataset, + Uint16& rspStatusCode); + + /** This function sends N-EVENT-REPORT request and receives the corresponding response + * @param presID [in] The ID of the presentation context to be used for sending + * the request message. Should not be 0. + * @param sopInstanceUID [in] The requested SOP Instance UID + * @param eventTypeID [in] The event type ID to be used + * @param reqDataset [in] The request dataset to be sent + * @param rspStatusCode [out] The response status code received. 0 means success, + * others can be found in the DICOM standard. + * @return EC_Normal if request could be issued and response was received successfully, + * an error code otherwise + */ + virtual OFCondition sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, + const OFString& sopInstanceUID, + const Uint16 eventTypeID, + DcmDataset* reqDataset, + Uint16& rspStatusCode); + + /** Receives N-EVENT-REPORT request on the currently opened association and sends a + * corresponding response. Calls checkEVENTREPORTRequest() in order to determine the + * DIMSE status code to be used for the N-EVENT-REPORT response. + * @param reqDataset [out] Pointer to the dataset received + * @param eventTypeID [out] Event Type ID from the command set received + * @param timeout [in] Optional timeout in seconds for receiving data. This value + * (if not 0) overwrites the standard DIMSE timeout and also + * enables the non-blocking mode for receiving the request. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition handleEVENTREPORTRequest(DcmDataset*& reqDataset, Uint16& eventTypeID, const int timeout = 0); + + /** Function handling a single C-GET, C-FIND or C-MOVE Response, used by + * handleCGETResponse(), handleFINDResponse() and handleMOVEResponse(). + * It prints a message to the logger (warning, error or debug level related + * to the status code provided) and sets waitForNextResponse if the status + * provided is a DIMSE pending status. + * @param dimseStatus [in] The DIMSE status code to handle + * @param message [in] The message to be printed + * @param waitForNextResponse [out] Defines whether it is decided to wait for further + * Responses with the C-GET/FIND/MOVE session. + * @return If no processing errors occurs this method will return EC_Normal, + * otherwise an error code. + */ + virtual OFCondition + handleSessionResponseDefault(const Uint16 dimseStatus, const OFString& message, OFBool& waitForNextResponse); - /** Sends a DIMSE command and possibly also a dataset from a data object via network to - * another DICOM application - * @param presID [in] Presentation context ID to be used for message - * @param msg [in] Structure that represents a certain DIMSE command which - * shall be sent - * @param dataObject [in] The instance data which shall be sent to the other DICOM - * application; NULL, if there is none - * @param commandSet [out] If this parameter is not NULL it will return a copy of the - * DIMSE command which is sent to the other DICOM application - * @return EC_Normal if sending request was successful, an error code otherwise - */ - OFCondition sendDIMSEMessage(const T_ASC_PresentationContextID presID, - T_DIMSE_Message *msg, - DcmDataset *dataObject, - DcmDataset **commandSet = NULL); - - /** Returns SOP Class UID, SOP Instance UID and original transfer syntax for a given dataset. - * If the dataset is NULL, all returned values will be undefined (i.e. empty or EXS_Unknown). - * @param dataset [in] The dataset to read from - * @param sopClassUID [out] The value of attribute SOP Class UID if present - * @param sopInstanceUID [out] The value of attribute SOP Instance UID if present - * @param transferSyntax [out] The value of transfer syntax that originally was read from - * disk. Will be unknown if the dataset was created in memory. - * @return EC_Normal if all information could be retrieved and is valid, an error code - * otherwise - */ - OFCondition getDatasetInfo(DcmDataset *dataset, - OFString &sopClassUID, - OFString &sopInstanceUID, - E_TransferSyntax &transferSyntax); - - /** Tells DcmSCU to use a secure TLS connection described by the given TLS layer - * @param tlayer [in] The TLS transport layer including all TLS parameters - * @return EC_Normal if given transport layer is ok, an error code otherwise - */ - OFCondition useSecureConnection(DcmTransportLayer *tlayer); - - /** Receive DIMSE command (excluding dataset!) over the currently open association - * @param presID [out] Contains in the end the ID of the presentation context - * which was specified in the DIMSE command received - * @param msg [out] The message received - * @param statusDetail [out] If a non-NULL value is passed this variable will in the end - * contain detailed information with regard to the status - * information which is captured in the status element - * (0000,0900). Note that the value for element (0000,0900) is - * not contained in this return value but in internal msg. For - * details on the structure of this object, see DICOM standard - * part 7, annex C). - * @param commandSet [out] If this parameter is not NULL, it will return a copy of the - * DIMSE command which was received from the other DICOM - * application. The caller is responsible to de-allocate the - * returned object! - * @param timeout [in] If this parameter is not 0, it specifies the timeout (in - * seconds) to be used for receiving the DIMSE command. - * Otherwise, the default timeout value is used (see - * setDIMSETimeout()). - * @return EC_Normal if command could be received successfully, an error code otherwise - */ - OFCondition receiveDIMSECommand(T_ASC_PresentationContextID *presID, - T_DIMSE_Message *msg, - DcmDataset **statusDetail, - DcmDataset **commandSet = NULL, - const Uint32 timeout = 0); - - /** Receives one dataset (of instance data) via network from another DICOM application - * @param presID [out] Contains in the end the ID of the presentation context which - * was used in the PDVs that were received on the network. If the - * PDVs show different presentation context IDs, this function - * will return an error. - * @param dataObject [out] Contains in the end the information which was received over - * the network - * @return EC_Normal if dataset could be received successfully, an error code otherwise - */ - OFCondition receiveDIMSEDataset(T_ASC_PresentationContextID *presID, - DcmDataset **dataObject); - - /** clear list of presentation contexts. In addition, any currently selected association - * configuration file is disabled. - */ - void clearPresentationContexts(); - - /** After negotiation association, this call returns the presentation context belonging - * to the given presentation context ID - * @param presID [in] The presentation context ID to look for - * @param abstractSyntax [out] The abstract syntax (UID) for that ID. - * Empty, if such a presentation context does not exist. - * @param transferSyntax [out] The transfer syntax (UID) for that ID. - * Empty, if such a presentation context does not exist. - */ - void findPresentationContext(const T_ASC_PresentationContextID presID, - OFString &abstractSyntax, - OFString &transferSyntax); - - /* *********************************************************************** - * Functions particularly interesting for overwriting in derived classes - * *********************************************************************** */ - - /** This function is called if an object was received due to a C-GET request and can be - * overwritten by a user in order to be informed about such an event. The default - * implementation just prints a DEBUG message. Note that this function is not called if - * the SCU is in storage mode DCMSCU_STORAGE_IGNORE. - * @param filename [in] The filename written - * @param sopClassUID [in] The SOP Class UID of the object written - * @param sopInstanceUID [in] The SOP Instance UID of the object written - */ - virtual void notifyInstanceStored(const OFString &filename, - const OFString &sopClassUID, - const OFString &sopInstanceUID) const; - - /** This function is called while sending DIMSE messages, i.e.\ on each PDV of a dataset. - * The default implementation just prints a TRACE message on the number of bytes sent so - * far. By overwriting this method, the progress of the send process can be shown to the - * user in a more appropriate way. The progress notification can also be disabled - * completely by calling setProgressNotificationMode(). - * @param byteCount [in] Number of bytes sent so far - */ - virtual void notifySENDProgress(const unsigned long byteCount); - - /** This function is called while receiving DIMSE messages, i.e.\ on each PDV of a dataset. - * The default implementation just prints a TRACE message on the number of bytes received - * so far. By overwriting this method, the progress of the receive process can be shown to - * the user in a more appropriate way. The progress notification can also be disabled - * completely by calling setProgressNotificationMode(). - * @param byteCount [in] Number of bytes received so far - */ - virtual void notifyRECEIVEProgress(const unsigned long byteCount); - - /** Check given N-EVENT-REPORT request and dataset for validity. This method is called by - * handleEVENTREPORTRequest() before sending the response in order to determine the - * DIMSE status code to be used for the response message. - * @param request [in] The N-EVENT-REPORT request message data structure - * @param reqDataset [in] The N-EVENT-REPORT request dataset received. Might be NULL. - * @return DIMSE status code to be used for the N-EVENT-REPORT response. - * Always returns STATUS_Success (0). Derived classes should, therefore, - * overwrite this method and return a more appropriate value based on the - * result of the checks performed. - */ - virtual Uint16 checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ &request, - DcmDataset *reqDataset); - - /** Sends back a C-STORE response on the given presentation context, with the designated - * status, fitting the corresponding C-STORE request. - * @param presID [in] The presentation context ID to be used. - * @param status [in] The storage DIMSE status to be used. - * @param request [in] The C-STORE request that should be responded to. - * @result EC_Normal if the response could be sent, error otherwise. - */ - virtual OFCondition sendSTOREResponse(T_ASC_PresentationContextID presID, - Uint16 status, - const T_DIMSE_C_StoreRQ &request); - - /** Helper function that generates a storage filename by extracting SOP Class and SOP - * Instance UID from a dataset and combining that with the configured storage directory. - * The SOP class is used to create an initial two letter abbreviation for the - * corresponding modality, e.g. CT. An example for a storage filename created by this - * function is "/storage_dir/CT.1.2.3.4.5" for a CT with SOP Instance UID "1.2.3.4.5". - * This function might be overwritten to change the filename behaviour completely. This - * function is only called if the SCU is in DCMSCU_STORAGE_DISK mode. - * @param dataset [in] The dataset that should be stored to disk - * @result Non-empty string if successful, otherwise empty string. - */ - virtual OFString createStorageFilename(DcmDataset *dataset); - - /** Receives a DICOM dataset on a given presentation context ID but does not store it in - * memory or disk, thus ignoring it. - * @param presID [in] The presentation context to be used - * @param request [in] The corresponding C-STORE request - * @return EC_Normal if ignoring worked, error code otherwise. - */ - virtual OFCondition ignoreSTORERequest(T_ASC_PresentationContextID presID, - const T_DIMSE_C_StoreRQ &request); - - /* Callback functions (static) */ - - /** Callback function used for sending DIMSE messages. - * @param callbackContext [in] The desired user callback data - * @param byteCount [in] Progress bytes count - */ - static void callbackSENDProgress(void *callbackContext, - unsigned long byteCount); - - /** Callback function used for receiving DIMSE messages. - * @param callbackContext [in] The desired user callback data - * @param byteCount [in] Progress bytes count - */ - static void callbackRECEIVEProgress(void *callbackContext, - unsigned long byteCount); + /** Closes the association created by this SCU. Also resets the current association. + * @deprecated The use of this method is deprecated. Please use releaseAssociation() + * or abortAssociation() instead. + * @param closeType [in] Define whether to release or abort the association + */ + virtual void closeAssociation(const DcmCloseAssociationType closeType); -private: + /** Releases the current association by sending an A-RELEASE request to the SCP. + * Please note that this release only applies to associations that have been + * created by calling initNetwork() and negotiateAssociation(). + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition releaseAssociation(); - /** Private undefined copy-constructor. Shall never be called. - * @param src Source object - */ - DcmSCU(const DcmSCU &src); + /** Aborts the current association by sending an A-ABORT request to the SCP. + * Please note that this abort only applies to associations that have been + * created by calling initNetwork() and negotiateAssociation(). + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition abortAssociation(); - /** Private undefined operator=. Shall never be called. - * @param src Source object - * @return Reference to this - */ - DcmSCU &operator=(const DcmSCU &src); + /* Set methods */ - /// Association of this SCU. This class only handles 1 association at a time. - T_ASC_Association *m_assoc; + /** Set maximum PDU length (to be received by SCU) + * @param maxRecPDU [in] The maximum PDU size to use in bytes + */ + void setMaxReceivePDULength(const Uint32 maxRecPDU); - /// The DICOM network the association is based on - T_ASC_Network *m_net; + /** Set whether to send in DIMSE blocking or non-blocking mode + * @param blockingMode [in] Either blocking or non-blocking mode + */ + void setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode); - /// Association parameters - T_ASC_Parameters *m_params; + /** Set SCU's AE title to be used in association negotiation + * @param myAETtitle [in] The SCU's AE title to be used + */ + void setAETitle(const OFString& myAETtitle); - /// Configuration file for presentation contexts (optional) - OFString m_assocConfigFilename; + /** Set SCP's host (host name or IP address) to talk to in association negotiation + * @param peerHostName [in] The SCP's hostname or IP address to be used + */ + void setPeerHostName(const OFString& peerHostName); - /// Profile in configuration file that should be used (optional) - OFString m_assocConfigProfile; + /** Set SCP's AE title to talk to in association negotiation + * @param peerAETitle [in] The SCP's AE title to be used + */ + void setPeerAETitle(const OFString& peerAETitle); - /// Defines presentation context, consisting of one abstract syntax name - /// and a list of transfer syntaxes for this abstract syntax - struct DCMTK_DCMNET_EXPORT DcmSCUPresContext { - /** Default constructor + /** Set SCP's port number to connect to for association negotiation + * @param peerPort [in] The SCP's port number */ - DcmSCUPresContext() - : abstractSyntaxName() - , transferSyntaxes() - , roleSelect(ASC_SC_ROLE_DEFAULT) - { - } - /// Abstract Syntax Name of Presentation Context - OFString abstractSyntaxName; - /// List of Transfer Syntaxes for Presentation Context - OFList transferSyntaxes; - /// Role Selection - T_ASC_SC_ROLE roleSelect; - }; + void setPeerPort(const Uint16 peerPort); + + /** Set timeout for receiving DIMSE messages + * @param dimseTimeout [in] DIMSE timeout in seconds for receiving data. + * If the blocking mode is DIMSE_NONBLOCKING the SCU + * will try to read data from the incoming socket stream + * for the number of seconds configured. + */ + void setDIMSETimeout(const Uint32 dimseTimeout); + + /** Set timeout for receiving ACSE messages + * @param acseTimeout [in] ACSE timeout in seconds used by timer for message timeouts + * during association negotiation + */ + void setACSETimeout(const Uint32 acseTimeout); + + /** Set global timeout for connecting to the SCP. Note that this is a global + * DCMTK setting i.e. it affects all code that uses dcmnet to start a DICOM + * association to another host. Setting the timeout to -1 sets an infinite timeout, + * i.e. any association request will wait forever (blocking) until the SCP accepts + * the connection request. A value of 0 lets the SCU return immediately if the SCP + * is not reachable at the first attempt. + * @param connectionTimeout [in] Connection Timeout in seconds when connecting + * to SCPs. -1 will wait forever (blocking mode). + */ + void setConnectionTimeout(const Sint32 connectionTimeout); + + /** Set an association configuration file and profile to be used + * @param filename [in] File name of the association configuration file + * @param profile [in] Profile inside the association negotiation file + */ + void setAssocConfigFileAndProfile(const OFString& filename, const OFString& profile); + + /** Set the directory that should be used by the standard C-GET handler to store objects + * that come in with the corresponding C-STORE requests + * @param storeDir [in] The directory to store to. It is checked in handleSTORERequest() + * whether the directory is writeable and readable. By default, the + * received objects are stored in the current working directory. + */ + void setStorageDir(const OFString& storeDir); + + /** Set the storage mode to be used. Default is DCMSCU_STORAGE_DISK. + * @param storageMode The storage mode to be used. + */ + void setStorageMode(const DcmStorageMode storageMode); + + /** Set whether to show presentation contexts in verbose or debug mode + * @param mode [in] Show presentation contexts in verbose mode if OFTrue. By default, + * the presentation contexts are shown in debug mode. + */ + void setVerbosePCMode(const OFBool mode); + + /** Set the mode that specifies whether the transfer syntax of the dataset can be changed + * for network transmission. This mainly covers the compression/decompression of datasets, + * which is disabled by default. + * @param mode [in] Allow dataset conversion if OFTrue + */ + void setDatasetConversionMode(const OFBool mode); + + /** Set the mode that specifies whether the progress of sending and receiving DIMSE + * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), + * respectively. The progress notification is enabled by default. + * @param mode [in] Disable progress notification if OFFalse + */ + void setProgressNotificationMode(const OFBool mode); + + /* Get methods */ + + /** Get current connection status + * @return OFTrue if SCU is currently connected, OFFalse otherwise + */ + OFBool isConnected() const; + + /** Returns maximum PDU length configured to be received by SCU + * @return Maximum PDU length in bytes + */ + Uint32 getMaxReceivePDULength() const; + + /** Returns whether DIMSE messaging is configured to be blocking or unblocking + * @return The blocking mode configured + */ + T_DIMSE_BlockingMode getDIMSEBlockingMode() const; + + /** Returns the SCU's own configured AE title + * @return The AE title configured for this SCU + */ + const OFString& getAETitle() const; + + /** Returns the SCP's (peer's) host configured + * @return The host name (or IP) configured to be talked to + */ + const OFString& getPeerHostName() const; + + /** Returns the SCP's (peer's) AE title configured + * @return The AE title configured to be talked to + */ + const OFString& getPeerAETitle() const; + + /** Returns the SCP's (peer's) TCP/IP port configured + * @return The port configured to talked to + */ + Uint16 getPeerPort() const; + + /** Returns DIMSE timeout in seconds for receiving data. If the blocking + * mode is DIMSE_NONBLOCKING the SCU will try to read data from + * the incoming socket stream for the number of seconds configured. + * @return The DIMSE timeout (in seconds) configured + */ + Uint32 getDIMSETimeout() const; - /// List of presentation contexts that should be negotiated - OFList m_presContexts; + /** Returns ACSE timeout in seconds used by timer for message timeouts during + * association negotiation. + * @return The ACSE timeout (in seconds) configured + */ + Uint32 getACSETimeout() const; - /// Configuration file containing association parameters - OFString m_assocConfigFile; + /** Returns the timeout configured defining how long SCU will wait for the + * SCP when requesting an association. -1 means infinite waiting (blocking), + * 0 means no waiting at all. Note that this is currently a global DCMTK setting. + * @return The connection timeout (in seconds) + */ + Sint32 getConnectionTimeout() const; - /// The last DIMSE successfully sent, unresponded DIMSE request - T_DIMSE_Message *m_openDIMSERequest; + /** Returns the storage directory used for storing objects received with C-STORE requests + * in the context of C-GET sessions. Default is empty string which refers to the current + * working directory. + * @return The storage directory + */ + OFString getStorageDir() const; - /// Maximum PDU size (default: 16384 bytes) - Uint32 m_maxReceivePDULength; + /** Returns the storage mode enabled + * @return The storage mode enabled + */ + DcmStorageMode getStorageMode() const; + + /** Returns the verbose presentation context mode configured specifying whether details + * on the presentation contexts (negotiated during association setup) should be shown in + * verbose or debug mode. The latter is the default. + * @return The current verbose presentation context mode. Show details on the + * presentation contexts on INFO log level (verbose) if OFTrue and on DEBUG + * level if OFFalse. + */ + OFBool getVerbosePCMode() const; - /// DIMSE blocking mode (default: blocking) - T_DIMSE_BlockingMode m_blockMode; + /** Returns the mode that specifies whether the transfer syntax of the dataset can be + * changed for network transmission. This mainly covers the compression/decompression + * of datasets, which is disabled by default. + * @return The current dataset conversion mode, enabled if OFTrue + */ + OFBool getDatasetConversionMode() const; - /// AE title of this application (default: ANY-SCU) - OFString m_ourAETitle; + /** Returns the mode that specifies whether the progress of sending and receiving DIMSE + * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(), + * respectively. The progress notification is enabled by default. + * @return The current progress notification mode, enabled if OFTrue + */ + OFBool getProgressNotificationMode() const; - /// Peer host (IP or host name) - OFString m_peer; + /** Returns whether SCU is configured to create a TLS connection with the SCP + * @return OFFalse for this class but may be overridden by derived classes + */ + OFBool getTLSEnabled() const; - /// AE title of remote application (default: ANY-SCP) - OFString m_peerAETitle; + /** Deletes internal networking structures from memory */ + void freeNetwork(); - /// Port of remote application entity (default: 104) - Uint16 m_peerPort; +protected: + /** Sends a DIMSE command and possibly also a dataset from a data object via network to + * another DICOM application + * @param presID [in] Presentation context ID to be used for message + * @param msg [in] Structure that represents a certain DIMSE command which + * shall be sent + * @param dataObject [in] The instance data which shall be sent to the other DICOM + * application; NULL, if there is none + * @param commandSet [out] If this parameter is not NULL it will return a copy of the + * DIMSE command which is sent to the other DICOM application + * @return EC_Normal if sending request was successful, an error code otherwise + */ + OFCondition sendDIMSEMessage(const T_ASC_PresentationContextID presID, + T_DIMSE_Message* msg, + DcmDataset* dataObject, + DcmDataset** commandSet = NULL); + + /** Returns SOP Class UID, SOP Instance UID and original transfer syntax for a given dataset. + * If the dataset is NULL, all returned values will be undefined (i.e. empty or EXS_Unknown). + * @param dataset [in] The dataset to read from + * @param sopClassUID [out] The value of attribute SOP Class UID if present + * @param sopInstanceUID [out] The value of attribute SOP Instance UID if present + * @param transferSyntax [out] The value of transfer syntax that originally was read from + * disk. Will be unknown if the dataset was created in memory. + * @return EC_Normal if all information could be retrieved and is valid, an error code + * otherwise + */ + OFCondition getDatasetInfo(DcmDataset* dataset, + OFString& sopClassUID, + OFString& sopInstanceUID, + E_TransferSyntax& transferSyntax); + + /** Tells DcmSCU to use a secure TLS connection described by the given TLS layer + * @param tlayer [in] The TLS transport layer including all TLS parameters + * @return EC_Normal if given transport layer is ok, an error code otherwise + */ + OFCondition useSecureConnection(DcmTransportLayer* tlayer); + + /** Receive DIMSE command (excluding dataset!) over the currently open association + * @param presID [out] Contains in the end the ID of the presentation context + * which was specified in the DIMSE command received + * @param msg [out] The message received + * @param statusDetail [out] If a non-NULL value is passed this variable will in the end + * contain detailed information with regard to the status + * information which is captured in the status element + * (0000,0900). Note that the value for element (0000,0900) is + * not contained in this return value but in internal msg. For + * details on the structure of this object, see DICOM standard + * part 7, annex C). + * @param commandSet [out] If this parameter is not NULL, it will return a copy of the + * DIMSE command which was received from the other DICOM + * application. The caller is responsible to de-allocate the + * returned object! + * @param timeout [in] If this parameter is not 0, it specifies the timeout (in + * seconds) to be used for receiving the DIMSE command. + * Otherwise, the default timeout value is used (see + * setDIMSETimeout()). + * @return EC_Normal if command could be received successfully, an error code otherwise + */ + OFCondition receiveDIMSECommand(T_ASC_PresentationContextID* presID, + T_DIMSE_Message* msg, + DcmDataset** statusDetail, + DcmDataset** commandSet = NULL, + const Uint32 timeout = 0); + + /** Receives one dataset (of instance data) via network from another DICOM application + * @param presID [out] Contains in the end the ID of the presentation context which + * was used in the PDVs that were received on the network. If the + * PDVs show different presentation context IDs, this function + * will return an error. + * @param dataObject [out] Contains in the end the information which was received over + * the network + * @return EC_Normal if dataset could be received successfully, an error code otherwise + */ + OFCondition receiveDIMSEDataset(T_ASC_PresentationContextID* presID, DcmDataset** dataObject); - /// DIMSE timeout (default: unlimited) - Uint32 m_dimseTimeout; + /** clear list of presentation contexts. In addition, any currently selected association + * configuration file is disabled. + */ + void clearPresentationContexts(); + + /** After negotiation association, this call returns the presentation context belonging + * to the given presentation context ID + * @param presID [in] The presentation context ID to look for + * @param abstractSyntax [out] The abstract syntax (UID) for that ID. + * Empty, if such a presentation context does not exist. + * @param transferSyntax [out] The transfer syntax (UID) for that ID. + * Empty, if such a presentation context does not exist. + */ + void findPresentationContext(const T_ASC_PresentationContextID presID, + OFString& abstractSyntax, + OFString& transferSyntax); + + /* *********************************************************************** + * Functions particularly interesting for overwriting in derived classes + * *********************************************************************** */ + + /** This function is called if an object was received due to a C-GET request and can be + * overwritten by a user in order to be informed about such an event. The default + * implementation just prints a DEBUG message. Note that this function is not called if + * the SCU is in storage mode DCMSCU_STORAGE_IGNORE. + * @param filename [in] The filename written + * @param sopClassUID [in] The SOP Class UID of the object written + * @param sopInstanceUID [in] The SOP Instance UID of the object written + */ + virtual void + notifyInstanceStored(const OFString& filename, const OFString& sopClassUID, const OFString& sopInstanceUID) const; + + /** This function is called while sending DIMSE messages, i.e.\ on each PDV of a dataset. + * The default implementation just prints a TRACE message on the number of bytes sent so + * far. By overwriting this method, the progress of the send process can be shown to the + * user in a more appropriate way. The progress notification can also be disabled + * completely by calling setProgressNotificationMode(). + * @param byteCount [in] Number of bytes sent so far + */ + virtual void notifySENDProgress(const unsigned long byteCount); + + /** This function is called while receiving DIMSE messages, i.e.\ on each PDV of a dataset. + * The default implementation just prints a TRACE message on the number of bytes received + * so far. By overwriting this method, the progress of the receive process can be shown to + * the user in a more appropriate way. The progress notification can also be disabled + * completely by calling setProgressNotificationMode(). + * @param byteCount [in] Number of bytes received so far + */ + virtual void notifyRECEIVEProgress(const unsigned long byteCount); + + /** Check given N-EVENT-REPORT request and dataset for validity. This method is called by + * handleEVENTREPORTRequest() before sending the response in order to determine the + * DIMSE status code to be used for the response message. + * @param request [in] The N-EVENT-REPORT request message data structure + * @param reqDataset [in] The N-EVENT-REPORT request dataset received. Might be NULL. + * @return DIMSE status code to be used for the N-EVENT-REPORT response. + * Always returns STATUS_Success (0). Derived classes should, therefore, + * overwrite this method and return a more appropriate value based on the + * result of the checks performed. + */ + virtual Uint16 checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& request, DcmDataset* reqDataset); + + /** Sends back a C-STORE response on the given presentation context, with the designated + * status, fitting the corresponding C-STORE request. + * @param presID [in] The presentation context ID to be used. + * @param status [in] The storage DIMSE status to be used. + * @param request [in] The C-STORE request that should be responded to. + * @result EC_Normal if the response could be sent, error otherwise. + */ + virtual OFCondition + sendSTOREResponse(T_ASC_PresentationContextID presID, Uint16 status, const T_DIMSE_C_StoreRQ& request); + + /** Helper function that generates a storage filename by extracting SOP Class and SOP + * Instance UID from a dataset and combining that with the configured storage directory. + * The SOP class is used to create an initial two letter abbreviation for the + * corresponding modality, e.g. CT. An example for a storage filename created by this + * function is "/storage_dir/CT.1.2.3.4.5" for a CT with SOP Instance UID "1.2.3.4.5". + * This function might be overwritten to change the filename behaviour completely. This + * function is only called if the SCU is in DCMSCU_STORAGE_DISK mode. + * @param dataset [in] The dataset that should be stored to disk + * @result Non-empty string if successful, otherwise empty string. + */ + virtual OFString createStorageFilename(DcmDataset* dataset); - /// ACSE timeout (default: 30 seconds) - Uint32 m_acseTimeout; + /** Receives a DICOM dataset on a given presentation context ID but does not store it in + * memory or disk, thus ignoring it. + * @param presID [in] The presentation context to be used + * @param request [in] The corresponding C-STORE request + * @return EC_Normal if ignoring worked, error code otherwise. + */ + virtual OFCondition ignoreSTORERequest(T_ASC_PresentationContextID presID, const T_DIMSE_C_StoreRQ& request); - /// Storage directory for objects received with C-STORE due to a running - /// C-GET session. By default, the received objects are stored in the current - /// working directory. - OFString m_storageDir; + /* Callback functions (static) */ - /// Set whether bit preserving storage should be enabled, i.e.\ any objects - /// retrieved via C-STORE should be written directly to disk without any data - /// correction/re-computation (e.g.\ group length calculations, padding, etc.). - /// This is especially interesting for retaining valid signatures, and also to - /// receive huge files which cannot be fully received in memory. - /// Default value: DCMSCU_STORAGE_DISK - DcmStorageMode m_storageMode; + /** Callback function used for sending DIMSE messages. + * @param callbackContext [in] The desired user callback data + * @param byteCount [in] Progress bytes count + */ + static void callbackSENDProgress(void* callbackContext, unsigned long byteCount); - /// Verbose PC mode (default: disabled) - OFBool m_verbosePCMode; + /** Callback function used for receiving DIMSE messages. + * @param callbackContext [in] The desired user callback data + * @param byteCount [in] Progress bytes count + */ + static void callbackRECEIVEProgress(void* callbackContext, unsigned long byteCount); - /// Dataset conversion mode (default: disabled) - OFBool m_datasetConversionMode; +private: + /** Private undefined copy-constructor. Shall never be called. + * @param src Source object + */ + DcmSCU(const DcmSCU& src); - /// Progress notification mode (default: enabled) - OFBool m_progressNotificationMode; + /** Private undefined operator=. Shall never be called. + * @param src Source object + * @return Reference to this + */ + DcmSCU& operator=(const DcmSCU& src); + + /// Association of this SCU. This class only handles 1 association at a time. + T_ASC_Association* m_assoc; + + /// The DICOM network the association is based on + T_ASC_Network* m_net; + + /// Association parameters + T_ASC_Parameters* m_params; - /** Returns next available message ID free to be used by SCU - * @return Next free message ID - */ - Uint16 nextMessageID(); + /// Configuration file for presentation contexts (optional) + OFString m_assocConfigFilename; + + /// Profile in configuration file that should be used (optional) + OFString m_assocConfigProfile; + + /// Defines presentation context, consisting of one abstract syntax name + /// and a list of transfer syntaxes for this abstract syntax + struct DCMTK_DCMNET_EXPORT DcmSCUPresContext + { + /** Default constructor + */ + DcmSCUPresContext() + : abstractSyntaxName() + , transferSyntaxes() + , roleSelect(ASC_SC_ROLE_DEFAULT) + { + } + /// Abstract Syntax Name of Presentation Context + OFString abstractSyntaxName; + /// List of Transfer Syntaxes for Presentation Context + OFList transferSyntaxes; + /// Role Selection + T_ASC_SC_ROLE roleSelect; + }; + + /// List of presentation contexts that should be negotiated + OFList m_presContexts; + + /// Configuration file containing association parameters + OFString m_assocConfigFile; + + /// The last DIMSE successfully sent, unresponded DIMSE request + T_DIMSE_Message* m_openDIMSERequest; + + /// Maximum PDU size (default: 16384 bytes) + Uint32 m_maxReceivePDULength; + + /// DIMSE blocking mode (default: blocking) + T_DIMSE_BlockingMode m_blockMode; + + /// AE title of this application (default: ANY-SCU) + OFString m_ourAETitle; + + /// Peer host (IP or host name) + OFString m_peer; + + /// AE title of remote application (default: ANY-SCP) + OFString m_peerAETitle; + + /// Port of remote application entity (default: 104) + Uint16 m_peerPort; + + /// DIMSE timeout (default: unlimited) + Uint32 m_dimseTimeout; + + /// ACSE timeout (default: 30 seconds) + Uint32 m_acseTimeout; + + /// Storage directory for objects received with C-STORE due to a running + /// C-GET session. By default, the received objects are stored in the current + /// working directory. + OFString m_storageDir; + + /// Set whether bit preserving storage should be enabled, i.e.\ any objects + /// retrieved via C-STORE should be written directly to disk without any data + /// correction/re-computation (e.g.\ group length calculations, padding, etc.). + /// This is especially interesting for retaining valid signatures, and also to + /// receive huge files which cannot be fully received in memory. + /// Default value: DCMSCU_STORAGE_DISK + DcmStorageMode m_storageMode; + + /// Verbose PC mode (default: disabled) + OFBool m_verbosePCMode; + + /// Dataset conversion mode (default: disabled) + OFBool m_datasetConversionMode; + + /// Progress notification mode (default: enabled) + OFBool m_progressNotificationMode; + + /** Returns next available message ID free to be used by SCU + * @return Next free message ID + */ + Uint16 nextMessageID(); }; #endif // SCU_H diff --git a/dcmnet/libsrc/Makefile.dep b/dcmnet/libsrc/Makefile.dep index 3753df2b..7400369e 100644 --- a/dcmnet/libsrc/Makefile.dep +++ b/dcmnet/libsrc/Makefile.dep @@ -1324,6 +1324,8 @@ dstorscp.o: dstorscp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h ../include/dcmtk/dcmnet/scp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -1349,8 +1351,6 @@ dstorscp.o: dstorscp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ @@ -1437,12 +1437,12 @@ dstorscp.o: dstorscp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h dstorscu.o: dstorscu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ @@ -1560,18 +1560,18 @@ dstorscu.o: dstorscu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ - ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dndefine.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/assoc.h \ ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ - ../../ofstd/include/dcmtk/ofstd/ofconsol.h ../include/dcmtk/dcmnet/lst.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dcasccff.h \ - ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ - ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ - ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ - ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/diutil.h + ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ + ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ + ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h dul.o: dul.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/dicom.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ @@ -1974,21 +1974,26 @@ lst.o: lst.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/dcmnet/dndefine.h scp.o: scp.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmnet/scp.h ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ @@ -2006,25 +2011,29 @@ scp.o: scp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/dntypes.h ../include/dcmtk/dcmnet/scp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ @@ -2087,20 +2096,12 @@ scp.o: scp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dicom.h \ - ../include/dcmtk/dcmnet/cond.h \ - ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ - ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ - ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ - ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcostrmf.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h scpcfg.o: scpcfg.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ @@ -2182,6 +2183,8 @@ scppool.o: scppool.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../include/dcmtk/dcmnet/scpthrd.h ../include/dcmtk/dcmnet/scp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -2207,8 +2210,6 @@ scppool.o: scppool.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ @@ -2294,14 +2295,16 @@ scppool.o: scppool.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h scpthrd.o: scpthrd.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmnet/scpthrd.h ../include/dcmtk/dcmnet/scp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -2334,8 +2337,6 @@ scpthrd.o: scpthrd.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ @@ -2422,30 +2423,33 @@ scpthrd.o: scpthrd.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h scu.o: scu.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmnet/scu.h ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ - ../../oflog/include/dcmtk/oflog/oflog.h \ - ../../oflog/include/dcmtk/oflog/logger.h \ - ../../oflog/include/dcmtk/oflog/config.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ @@ -2464,36 +2468,43 @@ scu.o: scu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ + ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/scu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ @@ -2542,16 +2553,7 @@ scu.o: scu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ - ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ - ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ - ../../ofstd/include/dcmtk/ofstd/ofconsol.h ../include/dcmtk/dcmnet/lst.h \ - ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ - ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dcasccff.h \ - ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ - ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ - ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ - ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/diutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcostrmf.h + ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ + ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ + ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ + ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h diff --git a/dcmnet/libsrc/assoc.cc b/dcmnet/libsrc/assoc.cc index d5741a69..6dbe4ef4 100644 --- a/dcmnet/libsrc/assoc.cc +++ b/dcmnet/libsrc/assoc.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -286,12 +286,12 @@ ASC_createAssociationParameters(T_ASC_Parameters ** params, if (*params == NULL) return EC_MemoryExhausted; bzero((char*)*params, sizeof(**params)); - strncpy((*params)->ourImplementationClassUID, + OFStandard::strlcpy((*params)->ourImplementationClassUID, OFFIS_IMPLEMENTATION_CLASS_UID, - sizeof((*params)->ourImplementationClassUID)-1); - strncpy((*params)->ourImplementationVersionName, + sizeof((*params)->ourImplementationClassUID)); + OFStandard::strlcpy((*params)->ourImplementationVersionName, OFFIS_DTK_IMPLEMENTATION_VERSION_NAME, - sizeof((*params)->ourImplementationVersionName)-1); + sizeof((*params)->ourImplementationVersionName)); if (strlen(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME) > 16) { @@ -303,9 +303,9 @@ ASC_createAssociationParameters(T_ASC_Parameters ** params, OFStandard::strlcpy((*params)->DULparams.callingImplementationVersionName, (*params)->ourImplementationVersionName, 16+1); - strncpy((*params)->DULparams.applicationContextName, + OFStandard::strlcpy((*params)->DULparams.applicationContextName, UID_StandardApplicationContext, - sizeof((*params)->DULparams.applicationContextName)-1); + sizeof((*params)->DULparams.applicationContextName)); ASC_setAPTitles(*params, "calling AP Title", @@ -391,14 +391,14 @@ ASC_setAPTitles(T_ASC_Parameters * params, const char* respondingAPTitle) { if (callingAPTitle) - strncpy(params->DULparams.callingAPTitle, callingAPTitle, - sizeof(params->DULparams.callingAPTitle)-1); + OFStandard::strlcpy(params->DULparams.callingAPTitle, callingAPTitle, + sizeof(params->DULparams.callingAPTitle)); if (calledAPTitle) - strncpy(params->DULparams.calledAPTitle, calledAPTitle, - sizeof(params->DULparams.calledAPTitle)-1); + OFStandard::strlcpy(params->DULparams.calledAPTitle, calledAPTitle, + sizeof(params->DULparams.calledAPTitle)); if (respondingAPTitle) - strncpy(params->DULparams.respondingAPTitle, respondingAPTitle, - sizeof(params->DULparams.respondingAPTitle)-1); + OFStandard::strlcpy(params->DULparams.respondingAPTitle, respondingAPTitle, + sizeof(params->DULparams.respondingAPTitle)); return EC_Normal; } @@ -440,13 +440,13 @@ ASC_setPresentationAddresses(T_ASC_Parameters * params, const char* calledPresentationAddress) { if (callingPresentationAddress) - strncpy(params->DULparams.callingPresentationAddress, + OFStandard::strlcpy(params->DULparams.callingPresentationAddress, callingPresentationAddress, - sizeof(params->DULparams.callingPresentationAddress)-1); + sizeof(params->DULparams.callingPresentationAddress)); if (calledPresentationAddress) - strncpy(params->DULparams.calledPresentationAddress, + OFStandard::strlcpy(params->DULparams.calledPresentationAddress, calledPresentationAddress, - sizeof(params->DULparams.calledPresentationAddress)-1); + sizeof(params->DULparams.calledPresentationAddress)); return EC_Normal; } @@ -1792,14 +1792,12 @@ ASC_receiveAssociation(T_ASC_Network * network, } // copy only maximum number of allowed characters - // trailing zero is always present because - // ASC_createAssociationParameters zero-initializes the complete struct. - strncpy(params->theirImplementationClassUID, + OFStandard::strlcpy(params->theirImplementationClassUID, params->DULparams.callingImplementationClassUID, - sizeof (params->theirImplementationClassUID) - 1); - strncpy(params->theirImplementationVersionName, + sizeof (params->theirImplementationClassUID)); + OFStandard::strlcpy(params->theirImplementationVersionName, params->DULparams.callingImplementationVersionName, - sizeof (params->theirImplementationVersionName) - 1); + sizeof (params->theirImplementationVersionName)); /* * The params->DULparams.peerMaxPDU parameter contains the diff --git a/dcmnet/libsrc/dfindscu.cc b/dcmnet/libsrc/dfindscu.cc index 9a4305c5..8af0721a 100644 --- a/dcmnet/libsrc/dfindscu.cc +++ b/dcmnet/libsrc/dfindscu.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -77,10 +77,12 @@ DcmFindSCUDefaultCallback::DcmFindSCUDefaultCallback( DcmFindSCUExtractMode extractResponses, int cancelAfterNResponses, const char *outputDirectory, - STD_NAMESPACE ofstream *outputStream) + STD_NAMESPACE ofstream *outputStream, + const unsigned int limitOutput) : DcmFindSCUCallback() , extractResponses_(extractResponses) , cancelAfterNResponses_(cancelAfterNResponses) +, limitOutput_(limitOutput) , outputDirectory_(OFSTRING_GUARD(outputDirectory)) , outputStream_(outputStream) { @@ -112,57 +114,70 @@ void DcmFindSCUDefaultCallback::callback( } else { DCMNET_INFO("Received Find Response " << responseCount << " (" << DU_cfindStatusString(rsp->DimseStatus) << ")"); } - - /* should we extract the response dataset to a DICOM file? */ - if (extractResponses_ == FEM_dicomFile) - { - OFString outputFilename; - char rspIdsFileName[32]; - sprintf(rspIdsFileName, "rsp%04d.dcm", responseCount); - OFStandard::combineDirAndFilename(outputFilename, outputDirectory_, rspIdsFileName, OFTrue /*allowEmptyDirName*/); - DCMNET_INFO("Writing response dataset to file: " << outputFilename); - DcmFindSCU::writeToFile(outputFilename.c_str(), responseIdentifiers); - } - /* ... or to an XML file? */ - else if (extractResponses_ == FEM_xmlFile) - { - OFString outputFilename; - char rspIdsFileName[32]; - sprintf(rspIdsFileName, "rsp%04d.xml", responseCount); - OFStandard::combineDirAndFilename(outputFilename, outputDirectory_, rspIdsFileName, OFTrue /*allowEmptyDirName*/); - DCMNET_INFO("Writing response dataset to file: " << outputFilename); - DcmFindSCU::writeToXMLFile(outputFilename.c_str(), responseIdentifiers); - } - /* ... or all responses to a single XML file? */ - else if (extractResponses_ == FEM_singleXMLFile) + /* should we extract the response dataset to file? */ + if (extractResponses_ != FEM_none) { - if (outputStream_ != NULL) + /* check for upper limit of extracted responses */ + if ((limitOutput_ > 0) && (OFstatic_cast(unsigned int, responseCount) > limitOutput_)) { - OFCondition cond = EC_Normal; - size_t writeFlags = 0; - DCMNET_DEBUG("Writing response dataset to XML file"); - /* expect that (0008,0005) is set if extended characters are used */ - if (responseIdentifiers->tagExistsWithValue(DCM_SpecificCharacterSet)) + /* output warning message on first response after limit has been reached */ + if (OFstatic_cast(unsigned int, responseCount) == limitOutput_ + 1) + DCMNET_INFO("Maximum number of responses already written to file ... not writing this and all following responses to file"); + else + DCMNET_DEBUG("Maximum number of responses already written to file ... not writing this response to file"); + } else { + /* should we extract the response dataset to a DICOM file? */ + if (extractResponses_ == FEM_dicomFile) + { + OFString outputFilename; + char rspIdsFileName[32]; + sprintf(rspIdsFileName, "rsp%04d.dcm", responseCount); + OFStandard::combineDirAndFilename(outputFilename, outputDirectory_, rspIdsFileName, OFTrue /*allowEmptyDirName*/); + DCMNET_INFO("Writing response dataset to file: " << outputFilename); + DcmFindSCU::writeToFile(outputFilename.c_str(), responseIdentifiers); + } + /* ... or to an XML file? */ + else if (extractResponses_ == FEM_xmlFile) + { + OFString outputFilename; + char rspIdsFileName[32]; + sprintf(rspIdsFileName, "rsp%04d.xml", responseCount); + OFStandard::combineDirAndFilename(outputFilename, outputDirectory_, rspIdsFileName, OFTrue /*allowEmptyDirName*/); + DCMNET_INFO("Writing response dataset to file: " << outputFilename); + DcmFindSCU::writeToXMLFile(outputFilename.c_str(), responseIdentifiers); + } + /* ... or all responses to a single XML file? */ + else if (extractResponses_ == FEM_singleXMLFile) { + if (outputStream_ != NULL) + { + OFCondition cond = EC_Normal; + size_t writeFlags = 0; + DCMNET_DEBUG("Writing response dataset to XML file"); + /* expect that (0008,0005) is set if extended characters are used */ + if (responseIdentifiers->tagExistsWithValue(DCM_SpecificCharacterSet)) + { #ifdef DCMTK_ENABLE_CHARSET_CONVERSION - DCMNET_DEBUG("Converting all element values that are affected by SpecificCharacterSet (0008,0005) to UTF-8"); - cond = responseIdentifiers->convertToUTF8(); + DCMNET_DEBUG("Converting all element values that are affected by SpecificCharacterSet (0008,0005) to UTF-8"); + cond = responseIdentifiers->convertToUTF8(); #else - if (responseIdentifiers->containsExtendedCharacters(OFFalse /*checkAllStrings*/)) - { - DCMNET_WARN("No support for character set conversion available ... quoting non-ASCII characters"); - /* make sure that non-ASCII characters are quoted appropriately */ - writeFlags |= DCMTypes::XF_convertNonASCII; - } else { - DCMNET_DEBUG("No support for character set conversion available"); - } + if (responseIdentifiers->containsExtendedCharacters(OFFalse /*checkAllStrings*/)) + { + DCMNET_WARN("No support for character set conversion available ... quoting non-ASCII characters"); + /* make sure that non-ASCII characters are quoted appropriately */ + writeFlags |= DCMTypes::XF_convertNonASCII; + } else { + DCMNET_DEBUG("No support for character set conversion available"); + } #endif + } + /* write response dataset to XML file */ + if (cond.good()) + cond = responseIdentifiers->writeXML(*outputStream_, writeFlags); + if (cond.bad()) + DCMNET_ERROR("Writing XML file: " << cond.text()); + } } - /* write response dataset to XML file */ - if (cond.good()) - cond = responseIdentifiers->writeXML(*outputStream_, writeFlags); - if (cond.bad()) - DCMNET_ERROR("Writing XML file: " << cond.text()); } } @@ -184,7 +199,8 @@ void DcmFindSCUDefaultCallback::callback( DcmFindSCU::DcmFindSCU() -: net_(NULL) +: net_(NULL), + outputResponseLimit_(0) { } @@ -193,6 +209,12 @@ DcmFindSCU::~DcmFindSCU() dropNetwork(); } +OFCondition DcmFindSCU::setOutputResponseLimit(const unsigned int limit) +{ + outputResponseLimit_ = limit; + return EC_Normal; +} + OFCondition DcmFindSCU::initializeNetwork(int acse_timeout) { return ASC_initializeNetwork(NET_REQUESTOR, 0, acse_timeout, &net_); @@ -250,7 +272,11 @@ OFCondition DcmFindSCU::performQuery( /* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */ OFCondition cond = ASC_createAssociationParameters(¶ms, maxReceivePDULength); - if (cond.bad()) return cond; + if (cond.bad()) + { + DCMNET_ERROR("Creating Association Parameters Failed: " << DimseCondition::dump(temp_str, cond)); + return cond; + } /* sets this application's title and the called application's title in the params */ /* structure. The default values to be set here are "FINDSCU" and "ANY-SCP". */ @@ -260,7 +286,12 @@ OFCondition DcmFindSCU::performQuery( /* structure. The default is an insecure connection; where OpenSSL is */ /* available the user is able to request an encrypted,secure connection. */ cond = ASC_setTransportLayerType(params, secureConnection); - if (cond.bad()) return cond; + if (cond.bad()) + { + DCMNET_ERROR("Setting Transport Layer Type Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociationParameters(¶ms); + return cond; + } /* Figure out the presentation addresses and copy the */ /* corresponding values into the association parameters.*/ @@ -270,7 +301,12 @@ OFCondition DcmFindSCU::performQuery( /* Set the presentation contexts which will be negotiated */ /* when the network connection will be established */ cond = addPresentationContext(params, abstractSyntax, preferredTransferSyntax); - if (cond.bad()) return cond; + if (cond.bad()) + { + DCMNET_ERROR("Adding Presentation Contexts Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociationParameters(¶ms); + return cond; + } /* dump presentation contexts if required */ DCMNET_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ)); @@ -283,14 +319,17 @@ OFCondition DcmFindSCU::performQuery( if (cond.bad()) { - if (cond == DUL_ASSOCIATIONREJECTED) { + if (cond == DUL_ASSOCIATIONREJECTED) + { T_ASC_RejectParameters rej; ASC_getRejectParameters(params, &rej); DCMNET_ERROR("Association Rejected:" << OFendl << ASC_printRejectParameters(temp_str, &rej)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } else { DCMNET_ERROR("Association Request Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } } @@ -300,8 +339,10 @@ OFCondition DcmFindSCU::performQuery( /* count the presentation contexts which have been accepted by the SCP */ /* If there are none, finish the execution */ - if (ASC_countAcceptedPresentationContexts(params) == 0) { + if (ASC_countAcceptedPresentationContexts(params) == 0) + { DCMNET_ERROR("No Acceptable Presentation Contexts"); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return NET_EC_NoAcceptablePresentationContexts; } @@ -362,6 +403,7 @@ OFCondition DcmFindSCU::performQuery( cond = ASC_abortAssociation(assoc); if (cond.bad()) { DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } } else { @@ -371,6 +413,7 @@ OFCondition DcmFindSCU::performQuery( if (cond.bad()) { DCMNET_ERROR("Association Release Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } } @@ -382,20 +425,20 @@ OFCondition DcmFindSCU::performQuery( cond = ASC_abortAssociation(assoc); if (cond.bad()) { DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } } else if (cond == DUL_PEERABORTEDASSOCIATION) { DCMNET_INFO("Peer Aborted Association"); - } - else - { + } else { DCMNET_ERROR("Find SCU Failed: " << DimseCondition::dump(temp_str, cond)); DCMNET_INFO("Aborting Association"); cond = ASC_abortAssociation(assoc); if (cond.bad()) { DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + (void) ASC_destroyAssociation(&assoc); // this also destroys the T_ASC_Parameters structure return cond; } } @@ -404,7 +447,9 @@ OFCondition DcmFindSCU::performQuery( /* call is the counterpart of ASC_requestAssociation(...) which was called above. */ cond = ASC_destroyAssociation(&assoc); if (cond.bad()) - DCMNET_ERROR(DimseCondition::dump(temp_str, cond)); + { + DCMNET_ERROR("Destroying Association Failed: " << DimseCondition::dump(temp_str, cond)); + } return cond; } @@ -648,7 +693,7 @@ OFCondition DcmFindSCU::findSCU( cond = proc.applyPathWithValue(dset, *path); if (cond.bad()) { - DCMNET_ERROR("Bad override key/path: " << *path << ": " << cond.text()); + DCMNET_ERROR("Bad override key/path: " << *path); return cond; } path++; @@ -658,7 +703,7 @@ OFCondition DcmFindSCU::findSCU( presId = ASC_findAcceptedPresentationContextID(assoc, abstractSyntax); if (presId == 0) { - DCMNET_ERROR("No presentation context"); + DCMNET_ERROR("No Presentation Context"); return DIMSE_NOVALIDPRESENTATIONCONTEXTID; } @@ -672,7 +717,7 @@ OFCondition DcmFindSCU::findSCU( req.Priority = DIMSE_PRIORITY_MEDIUM; /* prepare the callback data */ - DcmFindSCUDefaultCallback defaultCallback(extractResponses, cancelAfterNResponses, outputDirectory, outputStream); + DcmFindSCUDefaultCallback defaultCallback(extractResponses, cancelAfterNResponses, outputDirectory, outputStream, outputResponseLimit_); if (callback == NULL) callback = &defaultCallback; callback->setAssociation(assoc); callback->setPresentationContextID(presId); diff --git a/dcmnet/libsrc/dimdump.cc b/dcmnet/libsrc/dimdump.cc index 76e6ef9b..8c647b63 100644 --- a/dcmnet/libsrc/dimdump.cc +++ b/dcmnet/libsrc/dimdump.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1993-2019, OFFIS e.V. + * Copyright (C) 1993-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -66,339 +66,554 @@ static void DIMSE_dumpMessage_end(OFString &str, DcmItem *dataset = NULL) str += "======================= END DIMSE MESSAGE ======================="; } +static void DIMSE_printStatusClassString(STD_NAMESPACE ostream& dumpStream, int status) +{ + /* try to determine the Status Class of the DIMSE Status Code */ + if (DICOM_SUCCESS_STATUS(status)) + dumpStream << "Success"; + else if (DICOM_FAILURE_STATUS(status)) + dumpStream << "Failure"; + else if (DICOM_WARNING_STATUS(status)) + dumpStream << "Warning"; + else if (DICOM_CANCEL_STATUS(status)) + dumpStream << "Cancel"; + else if (DICOM_PENDING_STATUS(status)) + dumpStream << "Pending"; + else if (DICOM_STANDARD_STATUS(status)) + dumpStream << "Unknown Status Code"; + else + dumpStream << "Unknown Status Code (non-standard)"; +} + static void DIMSE_printNStatusString(STD_NAMESPACE ostream& dumpStream, int status) { + /* first, output the DIMSE status code in numeric format */ + dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(4) << status << ": "; + switch(status) { - case STATUS_Success: - dumpStream << "0x0000: Success"; + /* General DIMSE-N Codes */ + case STATUS_N_Success: + dumpStream << "Success"; + break; + case STATUS_N_Refused_NotAuthorized: + dumpStream << "Refused: Not authorized"; break; case STATUS_N_Cancel: - dumpStream << "0xFE00: Cancel"; + dumpStream << "Cancel"; break; case STATUS_N_AttributeListError: - dumpStream << "0x0107: Attribute list error"; + dumpStream << "Attribute list error"; break; case STATUS_N_SOPClassNotSupported: - dumpStream << "0x0122: SOP class not supported"; + dumpStream << "SOP Class not supported"; break; case STATUS_N_ClassInstanceConflict: - dumpStream << "0x0119: Class/instance conflict"; + dumpStream << "Class-Instance conflict"; break; case STATUS_N_DuplicateSOPInstance: - dumpStream << "0x0111: Duplicate SOP instance"; + dumpStream << "Duplicate SOP Instance"; break; case STATUS_N_DuplicateInvocation: - dumpStream << "0x0210: Duplicate invocation"; + dumpStream << "Duplicate invocation"; break; case STATUS_N_InvalidArgumentValue: - dumpStream << "0x0115: Invalid argument value"; + dumpStream << "Invalid argument value"; break; case STATUS_N_InvalidAttributeValue: - dumpStream << "0x0106: Invalid attribute value"; + dumpStream << "Invalid attribute value"; break; case STATUS_N_AttributeValueOutOfRange: - dumpStream << "0x0116: Attribute value out of range"; + dumpStream << "Attribute value out of range"; break; - case STATUS_N_InvalidObjectInstance: - dumpStream << "0x0117: Invalid object instance"; + case STATUS_N_InvalidSOPInstance: + dumpStream << "Invalid SOP Instance"; break; case STATUS_N_MissingAttribute: - dumpStream << "0x0120: Missing attribute"; + dumpStream << "Missing attribute"; break; case STATUS_N_MissingAttributeValue: - dumpStream << "0x0121: Missing attribute value"; + dumpStream << "Missing attribute value"; break; case STATUS_N_MistypedArgument: - dumpStream << "0x0212: Mistyped argument"; + dumpStream << "Mistyped argument"; + break; + case STATUS_N_NoSuchAction: + dumpStream << "No such action"; break; case STATUS_N_NoSuchArgument: - dumpStream << "0x0114: No such argument"; + dumpStream << "No such argument"; break; case STATUS_N_NoSuchAttribute: - dumpStream << "0x0105: No such attribute"; + dumpStream << "No such attribute"; break; case STATUS_N_NoSuchEventType: - dumpStream << "0x0113: No such event type"; + dumpStream << "No such Event Type"; break; - case STATUS_N_NoSuchObjectInstance: - dumpStream << "0x0112: No such object instance"; + case STATUS_N_NoSuchSOPInstance: + dumpStream << "No such SOP Instance"; break; case STATUS_N_NoSuchSOPClass: - dumpStream << "0x0118: No such SOP class"; + dumpStream << "No such SOP Class"; break; case STATUS_N_ProcessingFailure: - dumpStream << "0x0110: Processing failure"; + dumpStream << "Processing failure"; break; case STATUS_N_ResourceLimitation: - dumpStream << "0x0213: Resource limitation"; + dumpStream << "Resource limitation"; break; case STATUS_N_UnrecognizedOperation: - dumpStream << "0x0211: Unrecognized operation"; + dumpStream << "Unrecognized operation"; break; + + /* Print Management Service Class Specific Codes */ case STATUS_N_PRINT_BFS_Warn_MemoryAllocation: - dumpStream << "0xB600: Basic film session warning - Memory allocation"; + dumpStream << "Basic film session warning - Memory allocation"; break; case STATUS_N_PRINT_BFS_Warn_NoSessionPrinting: - dumpStream << "0xB601: Basic film session warning - No session printing"; + dumpStream << "Basic film session warning - No session printing"; break; case STATUS_N_PRINT_BFS_Warn_EmptyPage: - dumpStream << "0xB602: Basic film session warning - Empty page"; + dumpStream << "Basic film session warning - Empty page"; break; case STATUS_N_PRINT_BFB_Warn_EmptyPage: - dumpStream << "0xB603: Basic film box warning - Empty page"; + dumpStream << "Basic film box warning - Empty page"; + break; + case STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageDemagnified: + dumpStream << "Basic film session/box or image box warning - Image demagnified"; + break; + case STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageCropped: + dumpStream << "Basic film session/box or image box warning - Image cropped"; + break; + case STATUS_N_PRINT_BFS_BFB_IB_Warn_ImageDecimated: + dumpStream << "Basic film session/box or image box warning - Image decimated"; break; case STATUS_N_PRINT_BFS_Fail_NoFilmBox: - dumpStream << "0xC600: Basic film session failure - No film box"; + dumpStream << "Basic film session failure - No film box"; break; case STATUS_N_PRINT_BFS_Fail_PrintQueueFull: - dumpStream << "0xC601: Basic film session failure - Print queue full"; + dumpStream << "Basic film session failure - Print queue full"; break; - case STATUS_N_PRINT_BSB_Fail_PrintQueueFull: - dumpStream << "0xC602: Basic film box failure - Print queue full"; + case STATUS_N_PRINT_BFB_Fail_PrintQueueFull: + dumpStream << "Basic film box failure - Print queue full"; break; case STATUS_N_PRINT_BFS_BFB_Fail_ImageSize: - dumpStream << "0xC603: Basic film session/box failure - Image size"; + dumpStream << "Basic film session/box failure - Image size"; + break; + case STATUS_N_PRINT_BFS_BFB_Fail_PositionCollision: // retired + dumpStream << "Basic film session/box failure - Position collision (retired)"; + break; + case STATUS_N_PRINT_BFS_BFB_Fail_CombinedImageSize: + dumpStream << "Basic film session/box failure - Combined image size"; break; - case STATUS_N_PRINT_BFS_BFB_Fail_PositionCollision: - dumpStream << "0xC604: Basic film session/box failure - Position collision"; + case STATUS_N_PRINT_IB_Warn_MinMaxDensity: + dumpStream << "Image box warning - Min/Max density"; break; case STATUS_N_PRINT_IB_Fail_InsufficientMemory: - dumpStream << "0xC605: Image box failure - Insufficient memory"; + dumpStream << "Image box failure - Insufficient memory"; break; case STATUS_N_PRINT_IB_Fail_MoreThanOneVOILUT: - dumpStream << "0xC606: Image box failure - More than one VOI LUT"; + dumpStream << "Image box failure - More than one VOI LUT"; break; + + /* Modality Performed Procedure Step Retrieve SOP Class Specific Codes */ + case STATUS_N_MPPS_Warning_RequestedOptionalAttributesNotSupported: + dumpStream << "MPPS retrieve warning: Requested optional attributes not supported"; + break; + + /* Application Event Logging Service Class Specific Codes */ + case STATUS_N_LOG_Failure_ProceduralLoggingNotAvailable: + dumpStream << "Event logging failure - Procedural logging not available"; + break; + case STATUS_N_LOG_Failure_EventInformationDoesNotMatchTemplate: + dumpStream << "Event logging failure - Event information does not match template"; + break; + case STATUS_N_LOG_Failure_CannotMatchEventToCurrentStudy: + dumpStream << "Event logging failure - Cannot match event to a current study"; + break; + case STATUS_N_LOG_Failure_IDsInconsistentInMatchingCurrentStudy: + dumpStream << "Event logging failure - IDs inconsistent in matching a current study - Event not logged"; + break; + case STATUS_N_LOG_Warning_SynchronizationFrameOfReferenceDoesNotMatch: + dumpStream << "Event logging warning - Synchronization Frame of Reference does not match"; + break; + case STATUS_N_LOG_Warning_StudyInstanceUIDCoercion: + dumpStream << "Event logging warning - Study Instance UID coercion"; + break; + case STATUS_N_LOG_Warning_IDsInconsistentInMatchingCurrentStudy: + dumpStream << "Event logging warning - IDs inconsistent in matching a current study - Event logged"; + break; + + /* Media Creation Management Service Class Specific Codes */ + case STATUS_N_MEDIA_Failed_MediaCreationActionAlreadyReceived: + dumpStream << "Media creation failure - Action already received"; + break; + case STATUS_N_MEDIA_Failed_MediaCreationRequestAlreadyCompleted: + dumpStream << "Media creation failure - Request already completed"; + break; + case STATUS_N_MEDIA_Failed_MediaCreationRequestAlreadyInProgress: + dumpStream << "Media creation failure - Request already in progress"; + break; + case STATUS_N_MEDIA_Failed_CancellationDenied: + dumpStream << "Media creation failure - Cancellation denied"; + break; + + /* other codes (try to determine the Status Class) */ default: - dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << status << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); break; } } static void DIMSE_printCStoreStatusString(STD_NAMESPACE ostream& dumpStream, int status) { + /* first, output the DIMSE status code in numeric format */ dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << status; + << STD_NAMESPACE setw(4) << status << ": "; - if ((status & 0xff00) == STATUS_STORE_Refused_OutOfResources) + /* General C-STORE Codes */ + if (status == STATUS_STORE_Success) { - dumpStream << ": Error: Refused - Out of resources"; + dumpStream << "Success"; } else if (status == STATUS_STORE_Refused_SOPClassNotSupported) { - dumpStream << ": Error: Refused - SOP Class not supported"; + dumpStream << "Refused: SOP Class not supported"; } - else if ((status & 0xff00) == STATUS_STORE_Error_DataSetDoesNotMatchSOPClass) + else if (status == STATUS_STORE_Refused_NotAuthorized) { - dumpStream << ": Error: Refused - Data Set does not match SOP Class"; + dumpStream << "Refused: Not authorized"; } - else if ((status & 0xf000) == STATUS_STORE_Error_CannotUnderstand) + else if (status == STATUS_STORE_InvalidSOPClass) { - dumpStream << ": Error: Cannot understand"; + dumpStream << "Invalid SOP Class"; } - else if (status == STATUS_STORE_Warning_CoercionOfDataElements) + else if (status == STATUS_STORE_DuplicateInvocation) { - dumpStream << ": Warning: Coercion of data elements"; + dumpStream << "Duplicate invocation"; } - else if (status == STATUS_STORE_Warning_DataSetDoesNotMatchSOPClass) + else if (status == STATUS_STORE_UnrecognizedOperation) { - dumpStream << ": Warning: Data Set does not match SOP Class"; + dumpStream << "Unrecognized operation"; } - else if (status == STATUS_STORE_Warning_ElementsDiscarded) + else if (status == STATUS_STORE_MistypedArgument) { - dumpStream << ": Warning: Elements discarded"; + dumpStream << "Mistyped argument"; } - else if (DICOM_WARNING_STATUS(status)) + + /* Service Class Specific C-STORE Codes */ + else if ((status & 0xff00) == STATUS_STORE_Refused_OutOfResources) { - dumpStream << ": Warning"; + dumpStream << "Refused: Out of resources"; } - else if (DICOM_PENDING_STATUS(status)) + else if ((status & 0xff00) == STATUS_STORE_Error_DataSetDoesNotMatchSOPClass) + { + dumpStream << "Error: Data Set does not match SOP Class"; + } + else if ((status & 0xf000) == STATUS_STORE_Error_CannotUnderstand) { - dumpStream << ": Pending"; + dumpStream << "Error: Cannot understand"; } - else if (status == STATUS_Success) + else if (status == STATUS_STORE_Warning_CoercionOfDataElements) + { + dumpStream << "Warning: Coercion of Data Elements"; + } + else if (status == STATUS_STORE_Warning_DataSetDoesNotMatchSOPClass) { - dumpStream << ": Success"; + dumpStream << "Warning: Data Set does not match SOP Class"; } + else if (status == STATUS_STORE_Warning_ElementsDiscarded) + { + dumpStream << "Warning: Elements discarded"; + } + + /* other codes (try to determine the Status Class) */ else { - dumpStream << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); } } -static void DIMSE_printCFindStatusString(STD_NAMESPACE ostream& dumpStream, int status) +static void DIMSE_printCFindStatusString(STD_NAMESPACE ostream& dumpStream, int status, const char *sopClass) { + /* first, output the DIMSE status code in numeric format */ dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << status; + << STD_NAMESPACE setw(4) << status << ": "; - if ((status & 0xff00) == STATUS_FIND_Refused_OutOfResources) + /* General C-FIND Codes */ + if (status == STATUS_FIND_Refused_SOPClassNotSupported) { - dumpStream << ": Error: Refused - Out of resources"; + dumpStream << "Refused: SOP Class not supported"; } - else if (status == STATUS_FIND_Refused_SOPClassNotSupported) + + /* Service Class Specific C-FIND Codes */ + else if (status == STATUS_FIND_Success_MatchingIsComplete) { - dumpStream << ": Error: Refused - SOP Class not supported"; + dumpStream << "Success: Matching is complete"; } - else if ((status & 0xff00) == STATUS_FIND_Failed_IdentifierDoesNotMatchSOPClass) + else if (status == STATUS_FIND_Refused_OutOfResources) { - dumpStream << ": Error: Failed - Identifier does not match SOP Class"; + dumpStream << "Refused: Out of resources"; } - else if ((status & 0xf000) == STATUS_FIND_Failed_UnableToProcess) + else if ((status & 0xff00) == STATUS_FIND_Error_DataSetDoesNotMatchSOPClass) { - dumpStream << ": Error: Failed - Unable to process"; + dumpStream << "Error: Data Set does not match SOP Class"; } - else if (status == STATUS_FIND_Cancel_MatchingTerminatedDueToCancelRequest) - { - dumpStream << ": Cancel: Matching terminated due to Cancel Request"; - } - else if (status == STATUS_FIND_Pending_WarningUnsupportedOptionalKeys) + else if ((status & 0xf000) == STATUS_FIND_Failed_UnableToProcess) { - dumpStream << ": Pending: Warning - Unsupported optional keys"; + /* Relevant Patient Information Query uses some specific Codes in "Cxxx" */ + if (sopClass && (strncmp(sopClass, UID_RelevantPatientInformationQuery_Prefix, strlen(UID_RelevantPatientInformationQuery_Prefix)) == 0)) + { + if (status == STATUS_FIND_Failed_MoreThanOneMatchFound) + { + dumpStream << "Failed: More than one match found"; + } + else if (status == STATUS_FIND_Failed_UnableToSupportRequestedTemplate) + { + dumpStream << "Failed: Unable to support requested template"; + } + else + { + dumpStream << "Failed: Unable to process"; + } + } + /* for all other Services Classes, the generic output is used */ + else + { + dumpStream << "Failed: Unable to process"; + } } - else if (DICOM_WARNING_STATUS(status)) + else if (status == STATUS_FIND_Cancel_MatchingTerminatedDueToCancelRequest) { - dumpStream << ": Warning"; + dumpStream << "Cancel: Matching terminated due to Cancel Request"; } - else if (DICOM_PENDING_STATUS(status)) + else if (status == STATUS_FIND_Pending_MatchesAreContinuing) { - dumpStream << ": Pending"; + dumpStream << "Pending: Matches are continuing"; } - else if (status == STATUS_Success) + else if (status == STATUS_FIND_Pending_WarningUnsupportedOptionalKeys) { - dumpStream << ": Success"; + dumpStream << "Pending: Matches are continuing - Warning: Unsupported optional keys"; } + + /* other codes (try to determine the Status Class) */ else { - dumpStream << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); } } static void DIMSE_printCGetStatusString(STD_NAMESPACE ostream& dumpStream, int status) { + /* first, output the DIMSE status code in numeric format */ dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << status; + << STD_NAMESPACE setw(4) << status << ": "; + + /* General C-GET Codes */ + if (status == STATUS_GET_Refused_SOPClassNotSupported) + { + dumpStream << "Refused: SOP Class not supported"; + } + else if (status == STATUS_GET_DuplicateInvocation) + { + dumpStream << "Duplicate invocation"; + } + else if (status == STATUS_GET_UnrecognizedOperation) + { + dumpStream << "Unrecognized operation"; + } + else if (status == STATUS_GET_MistypedArgument) + { + dumpStream << "Mistyped argument"; + } - if ((status & 0xf000) == STATUS_GET_Failed_UnableToProcess) + /* Service Class Specific C-GET Codes */ + else if (status == STATUS_GET_Success_SubOperationsCompleteNoFailures) { - dumpStream << ": Error: Failed - Unable to process"; + dumpStream << "Success: Sub-operations complete - No failures or warnings"; } else if (status == STATUS_GET_Refused_OutOfResourcesNumberOfMatches) { - dumpStream << ": Error: Refused - Out of resources - Number of matches"; + dumpStream << "Refused: Out of resources - Unable to calculate number of matches"; } else if (status == STATUS_GET_Refused_OutOfResourcesSubOperations) { - dumpStream << ": Error: Refused - Out of resources - Suboperations"; + dumpStream << "Refused: Out of resources - Unable to perform sub-operations"; } - else if (status == STATUS_GET_Failed_SOPClassNotSupported) + else if (status == STATUS_GET_Error_DataSetDoesNotMatchSOPClass) { - dumpStream << ": Failed: SOP Class not supported"; + dumpStream << "Error: Data Set does not match SOP Class"; } - else if (status == STATUS_GET_Failed_IdentifierDoesNotMatchSOPClass) + else if (status == STATUS_GET_Failed_NoneOfTheFramesWereFoundInSOPInstance) { - dumpStream << ": Failed: Identifier does not match SOP Class"; + dumpStream << "Failed: None of the frames requested were found in SOP Instance"; } - else if (status == STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication) + else if (status == STATUS_GET_Failed_UnableToCreateNewObjectForThisSOPClass) { - dumpStream << ": Cancel: Suboperations terminated due to Cancel Indication"; + dumpStream << "Failed: Unable to create new object for this SOP Class"; } - else if (status == STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures) + else if (status == STATUS_GET_Failed_UnableToExtractFrames) { - dumpStream << ": Warning: Suboperations complete, one or more failures"; + dumpStream << "Failed: Unable to extract frames"; } - else if (DICOM_WARNING_STATUS(status)) + else if (status == STATUS_GET_Failed_TimeBasedRequestForNonTimeBasedSOPInstance) { - dumpStream << ": Warning"; + dumpStream << "Failed: Time-based request for non-time-based SOP Instance"; } - else if (DICOM_PENDING_STATUS(status)) + else if (status == STATUS_GET_Failed_InvalidRequest) + { + dumpStream << "Failed: Invalid request"; + } + else if ((status & 0xf000) == STATUS_GET_Failed_UnableToProcess) { - dumpStream << ": Pending"; + dumpStream << "Failed: Unable to process"; } - else if (status == STATUS_Success) + else if (status == STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication) { - dumpStream << ": Success"; + dumpStream << "Cancel: Sub-operations terminated due to Cancel Indication"; } + else if (status == STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures) + { + dumpStream << "Warning: Sub-operations complete - One or more failures or warnings"; + } + else if (status == STATUS_GET_Pending_SubOperationsAreContinuing) + { + dumpStream << "Pending: Sub-operations are continuing"; + } + + /* other codes (try to determine the Status Class) */ else { - dumpStream << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); } } static void DIMSE_printCMoveStatusString(STD_NAMESPACE ostream& dumpStream, int status) { + /* first, output the DIMSE status code in numeric format */ dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << status; + << STD_NAMESPACE setw(4) << status << ": "; + + /* General C-MOVE Codes */ + if (status == STATUS_MOVE_Refused_SOPClassNotSupported) + { + dumpStream << "Refused: SOP Class not supported"; + } + else if (status == STATUS_MOVE_Refused_NotAuthorized) + { + dumpStream << "Refused: Not authorized"; + } + else if (status == STATUS_MOVE_DuplicateInvocation) + { + dumpStream << "Duplicate invocation"; + } + else if (status == STATUS_MOVE_UnrecognizedOperation) + { + dumpStream << "Unrecognized operation"; + } + else if (status == STATUS_MOVE_MistypedArgument) + { + dumpStream << "Mistyped argument"; + } - if ((status & 0xf000) == STATUS_MOVE_Failed_UnableToProcess) + /* Service Class Specific C-MOVE Codes */ + else if (status == STATUS_MOVE_Success_SubOperationsCompleteNoFailures) { - dumpStream << ": Error: Failed - Unable to process"; + dumpStream << "Success: Sub-operations complete - No failures or warnings"; } else if (status == STATUS_MOVE_Refused_OutOfResourcesNumberOfMatches) { - dumpStream << ": Error: Refused - Out of resources - Number of matches"; + dumpStream << "Refused: Out of resources - Unable to calculate number of matches"; } else if (status == STATUS_MOVE_Refused_OutOfResourcesSubOperations) { - dumpStream << ": Error: Refused - Out of resources - Suboperations"; + dumpStream << "Refused: Out of resources - Unable to perform sub-operations"; } - else if (status == STATUS_MOVE_Failed_SOPClassNotSupported) + else if (status == STATUS_MOVE_Refused_MoveDestinationUnknown) { - dumpStream << ": Failed: SOP Class not supported"; + dumpStream << "Refused: Move Destination unknown"; } - else if (status == STATUS_MOVE_Failed_MoveDestinationUnknown) + else if (status == STATUS_MOVE_Error_DataSetDoesNotMatchSOPClass) { - dumpStream << ": Failed: Move Destination unknown"; + dumpStream << "Error: Data Set does not match SOP Class"; } - else if (status == STATUS_MOVE_Failed_IdentifierDoesNotMatchSOPClass) + else if (status == STATUS_MOVE_Failed_NoneOfTheFramesWereFoundInSOPInstance) { - dumpStream << ": Failed: Identifier does not match SOP Class"; + dumpStream << "Failed: None of the frames requested were found in SOP Instance"; } - else if (status == STATUS_MOVE_Cancel_SubOperationsTerminatedDueToCancelIndication) + else if (status == STATUS_MOVE_Failed_UnableToCreateNewObjectForThisSOPClass) { - dumpStream << ": Cancel: Suboperations terminated due to Cancel Indication"; + dumpStream << "Failed: Unable to create new object for this SOP Class"; } - else if (status == STATUS_MOVE_Warning_SubOperationsCompleteOneOrMoreFailures) + else if (status == STATUS_MOVE_Failed_UnableToExtractFrames) { - dumpStream << ": Warning: Suboperations complete, one or more failures"; + dumpStream << "Failed: Unable to extract frames"; } - else if (DICOM_WARNING_STATUS(status)) + else if (status == STATUS_MOVE_Failed_TimeBasedRequestForNonTimeBasedSOPInstance) { - dumpStream << ": Warning"; + dumpStream << "Failed: Time-based request for non-time-based SOP Instance"; } - else if (DICOM_PENDING_STATUS(status)) + else if (status == STATUS_MOVE_Failed_InvalidRequest) { - dumpStream << ": Pending"; + dumpStream << "Failed: Invalid request"; } - else if (status == STATUS_Success) + else if ((status & 0xf000) == STATUS_MOVE_Failed_UnableToProcess) { - dumpStream << ": Success"; + dumpStream << "Failed: Unable to process"; } + else if (status == STATUS_MOVE_Cancel_SubOperationsTerminatedDueToCancelIndication) + { + dumpStream << "Cancel: Sub-operations terminated due to Cancel Indication"; + } + else if (status == STATUS_MOVE_Warning_SubOperationsCompleteOneOrMoreFailures) + { + dumpStream << "Warning: Sub-operations complete - One or more failures or warnings"; + } + else if (status == STATUS_MOVE_Pending_SubOperationsAreContinuing) + { + dumpStream << "Pending: Sub-operations are continuing"; + } + + /* other codes (try to determine the Status Class) */ else { - dumpStream << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); } } static void DIMSE_printCEchoStatusString(STD_NAMESPACE ostream& dumpStream, int status) { + /* first, output the DIMSE status code in numeric format */ dumpStream << "0x" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') - << STD_NAMESPACE setw(4) << status; - if (DICOM_WARNING_STATUS(status)) + << STD_NAMESPACE setw(4) << status << ": "; + + /* General C-ECHO Codes */ + if (status == STATUS_ECHO_Success) { - dumpStream << ": Warning"; + dumpStream << "Success"; } - else if (DICOM_PENDING_STATUS(status)) + else if (status == STATUS_ECHO_Refused_SOPClassNotSupported) { - dumpStream << ": Pending"; + dumpStream << "Refused: SOP Class not supported"; } - else if (status == STATUS_Success) + else if (status == STATUS_ECHO_DuplicateInvocation) { - dumpStream << ": Success"; + dumpStream << "Duplicate invocation"; } + else if (status == STATUS_ECHO_UnrecognizedOperation) + { + dumpStream << "Unrecognized operation"; + } + else if (status == STATUS_ECHO_MistypedArgument) + { + dumpStream << "Mistyped argument"; + } + + /* other codes (so try to determine the Status Class) */ else { - dumpStream << ": Unknown Status Code"; + DIMSE_printStatusClassString(dumpStream, status); } } @@ -728,10 +943,10 @@ OFString& DIMSE_dumpMessage(OFString &str, T_DIMSE_C_FindRQ &msg, enum DIMSE_dir OFString& DIMSE_dumpMessage(OFString &str, T_DIMSE_C_FindRSP &msg, enum DIMSE_direction dir, DcmItem *dataset, T_ASC_PresentationContextID presID) { OFOStringStream stream; - const char *uid = NULL; + const char *sopClassUID = (msg.opts & O_FIND_AFFECTEDSOPCLASSUID) ? msg.AffectedSOPClassUID : NULL; + const char *sopClassName = dcmFindNameOfUID(sopClassUID); DIMSE_dumpMessage_start(str, dir); - if (msg.opts & O_FIND_AFFECTEDSOPCLASSUID) uid = dcmFindNameOfUID(msg.AffectedSOPClassUID); stream << "Message Type : C-FIND RSP" << OFendl; if (presID > 0) { @@ -739,11 +954,15 @@ OFString& DIMSE_dumpMessage(OFString &str, T_DIMSE_C_FindRSP &msg, enum DIMSE_di } stream << "Message ID Being Responded To : " << msg.MessageIDBeingRespondedTo << OFendl << "Affected SOP Class UID : "; - if (msg.opts & O_FIND_AFFECTEDSOPCLASSUID) stream << (uid ? uid : msg.AffectedSOPClassUID) << OFendl; - else stream << "none" << OFendl; + if (sopClassName) + stream << sopClassName << OFendl; + else if (sopClassUID) + stream << sopClassUID << OFendl; + else + stream << "none" << OFendl; stream << "Data Set : " << ((msg.DataSetType==DIMSE_DATASET_NULL) ? "none" : "present") << OFendl << "DIMSE Status : "; - DIMSE_printCFindStatusString(stream, msg.DimseStatus); + DIMSE_printCFindStatusString(stream, msg.DimseStatus, sopClassUID); OFSTRINGSTREAM_GETSTR(stream, result) str += result; diff --git a/dcmnet/libsrc/dimfind.cc b/dcmnet/libsrc/dimfind.cc index 235dd378..1fd98e2f 100644 --- a/dcmnet/libsrc/dimfind.cc +++ b/dcmnet/libsrc/dimfind.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -144,7 +144,7 @@ DIMSE_findUser( T_DIMSE_Message req, rsp; DIC_US msgId; DcmDataset *rspIds = NULL; - DIC_US status = STATUS_Pending; + DIC_US status = STATUS_FIND_Pending_MatchesAreContinuing; /* if there is no search mask, nothing can be searched for */ if (requestIdentifiers == NULL) return DIMSE_NULLKEY; @@ -168,7 +168,7 @@ DIMSE_findUser( if (cond.bad()) return cond; /* try to receive (one or more) C-STORE-RSP messages, continue loop as long */ - /* as no error occured and not all result information has been received. */ + /* as no error occurred and not all result information has been received. */ while (cond == EC_Normal && DICOM_PENDING_STATUS(status)) { /* initialize the response to collect */ @@ -211,7 +211,7 @@ DIMSE_findUser( /* depending on the status which was returned in the current C-FIND-RSP, we need to do something */ switch (status) { - case STATUS_Pending: + case STATUS_FIND_Pending_MatchesAreContinuing: case STATUS_FIND_Pending_WarningUnsupportedOptionalKeys: /* in these cases we received a C-FIND-RSP which indicates that a result data set was */ /* found and will be sent over the network. We need to receive this result data set. */ @@ -243,7 +243,7 @@ DIMSE_findUser( response, rspIds); } break; - case STATUS_Success: + case STATUS_FIND_Success: /* in this case the current C-FIND-RSP indicates that */ /* there are no more records that match the search mask */ @@ -333,7 +333,7 @@ DIMSE_findProvider( /* * This function receives a data set which represents the search mask over the network and * stores this data in memory. Then, it tries to select corresponding records which match the - * search mask from some database (done whithin the callback function) and sends corresponding + * search mask from some database (done within the callback function) and sends corresponding * C-FIND-RSP messages to the other DICOM application this application is connected with. * The selection of each matching record and the sending of a corresponding C-FIND-RSP message * is conducted in a loop since there can be more than one search result. In the end, also the @@ -362,7 +362,7 @@ DIMSE_findProvider( /* receive data (i.e. the search mask) and store it in memory */ OFCondition cond = DIMSE_receiveDataSetInMemory(assoc, blockMode, timeout, &presIdData, &reqIds, NULL, NULL); - /* if no error occured while receiving data */ + /* if no error occurred while receiving data */ if (cond.good()) { /* check if the presentation context IDs of the C-FIND-RQ and */ @@ -376,11 +376,11 @@ DIMSE_findProvider( /* if the IDs are the same go ahead */ /* initialize the C-FIND-RSP message variable */ bzero((char*)&rsp, sizeof(rsp)); - rsp.DimseStatus = STATUS_Pending; + rsp.DimseStatus = STATUS_FIND_Pending_MatchesAreContinuing; - /* as long as no error occured and the status of the C-FIND-RSP message which will */ + /* as long as no error occurred and the status of the C-FIND-RSP message which will */ /* be/was sent is pending, perform this loop in which records that match the search */ - /* mask are selected (whithin the execution of the callback function) and sent over */ + /* mask are selected (within the execution of the callback function) and sent over */ /* the network to the other DICOM application using C-FIND-RSP messages. */ while (cond.good() && DICOM_PENDING_STATUS(rsp.DimseStatus) && normal) { @@ -400,7 +400,7 @@ DIMSE_findProvider( } else { - /* some execption condition occured, bail out */ + /* some exception condition occurred, bail out */ normal = OFFalse; } diff --git a/dcmnet/libsrc/dimget.cc b/dcmnet/libsrc/dimget.cc index e3c22495..f1375c69 100644 --- a/dcmnet/libsrc/dimget.cc +++ b/dcmnet/libsrc/dimget.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -100,7 +100,7 @@ DIMSE_getUser( DIC_US msgId; int responseCount = 0; T_ASC_Association *subAssoc = NULL; - DIC_US status = STATUS_Pending; + DIC_US status = STATUS_GET_Pending_SubOperationsAreContinuing; if (requestIdentifiers == NULL) return DIMSE_NULLKEY; @@ -184,7 +184,7 @@ DIMSE_getUser( responseCount++; switch (status) { - case STATUS_Pending: + case STATUS_GET_Pending_SubOperationsAreContinuing: if (*statusDetail != NULL) { DCMNET_WARN(DIMSE_warn_str(assoc) << "getUser: Pending with statusDetail, ignoring detail"); delete *statusDetail; @@ -238,14 +238,14 @@ DIMSE_sendGetResponse(T_ASC_Association * assoc, rsp.msg.CGetRSP = *response; /* copy over stuff from request */ rsp.msg.CGetRSP.MessageIDBeingRespondedTo = request->MessageID; - /* always send afected sop class uid */ + /* always send affected sop class uid */ OFStandard::strlcpy(rsp.msg.CGetRSP.AffectedSOPClassUID, request->AffectedSOPClassUID, sizeof(rsp.msg.CGetRSP.AffectedSOPClassUID)); rsp.msg.CGetRSP.opts = O_GET_AFFECTEDSOPCLASSUID; switch (response->DimseStatus) { - case STATUS_Success: - case STATUS_Pending: + case STATUS_GET_Success: + case STATUS_GET_Pending_SubOperationsAreContinuing: /* Success cannot have a Failed SOP Instance UID list (no failures). * Pending may not send such a list. */ @@ -269,7 +269,7 @@ DIMSE_sendGetResponse(T_ASC_Association * assoc, O_GET_NUMBEROFWARNINGSUBOPERATIONS); switch (response->DimseStatus) { - case STATUS_Pending: + case STATUS_GET_Pending_SubOperationsAreContinuing: case STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication: break; default: @@ -315,9 +315,9 @@ DIMSE_getProvider( else { bzero((char*)&rsp, sizeof(rsp)); - rsp.DimseStatus = STATUS_Pending; /* assume */ + rsp.DimseStatus = STATUS_GET_Pending_SubOperationsAreContinuing; /* assume */ - while (cond == EC_Normal && rsp.DimseStatus == STATUS_Pending && normal) + while (cond == EC_Normal && rsp.DimseStatus == STATUS_GET_Pending_SubOperationsAreContinuing && normal) { responseCount++; @@ -330,7 +330,7 @@ DIMSE_getProvider( } else if (cond == DIMSE_NODATAAVAILABLE) { /* timeout */ } else { - /* some execption condition occured, bail out */ + /* some exception condition occurred, bail out */ normal = OFFalse; } diff --git a/dcmnet/libsrc/dimmove.cc b/dcmnet/libsrc/dimmove.cc index e04a6a04..01a4fb9e 100644 --- a/dcmnet/libsrc/dimmove.cc +++ b/dcmnet/libsrc/dimmove.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -165,7 +165,7 @@ DIMSE_moveUser( DIC_US msgId; int responseCount = 0; T_ASC_Association *subAssoc = NULL; - DIC_US status = STATUS_Pending; + DIC_US status = STATUS_MOVE_Pending_SubOperationsAreContinuing; OFBool firstLoop = OFTrue; if (requestIdentifiers == NULL) return DIMSE_NULLKEY; @@ -187,7 +187,7 @@ DIMSE_moveUser( /* receive responses */ OFTimer timer; - while (cond == EC_Normal && status == STATUS_Pending) { + while (cond == EC_Normal && status == STATUS_MOVE_Pending_SubOperationsAreContinuing) { /* if user wants, multiplex between net/subAssoc * and move responses over main assoc. @@ -239,7 +239,7 @@ DIMSE_moveUser( responseCount++; switch (status) { - case STATUS_Pending: + case STATUS_MOVE_Pending_SubOperationsAreContinuing: if (*statusDetail != NULL) { DCMNET_WARN(DIMSE_warn_str(assoc) << "moveUser: Pending with statusDetail, ignoring detail"); delete *statusDetail; @@ -318,8 +318,8 @@ DIMSE_sendMoveResponse( rsp.msg.CMoveRSP.opts = O_MOVE_AFFECTEDSOPCLASSUID; switch (response->DimseStatus) { - case STATUS_Success: - case STATUS_Pending: + case STATUS_MOVE_Success: + case STATUS_MOVE_Pending_SubOperationsAreContinuing: /* Success cannot have a Failed SOP Instance UID list (no failures). * Pending may not send such a list. */ @@ -343,7 +343,7 @@ DIMSE_sendMoveResponse( O_MOVE_NUMBEROFWARNINGSUBOPERATIONS); switch (response->DimseStatus) { - case STATUS_Pending: + case STATUS_MOVE_Pending_SubOperationsAreContinuing: case STATUS_MOVE_Cancel_SubOperationsTerminatedDueToCancelIndication: break; default: @@ -389,9 +389,9 @@ DIMSE_moveProvider( cond = makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, "DIMSE: Presentation Contexts of Command and Data Differ"); } else { bzero((char*)&rsp, sizeof(rsp)); - rsp.DimseStatus = STATUS_Pending; /* assume */ + rsp.DimseStatus = STATUS_MOVE_Pending_SubOperationsAreContinuing; /* assume */ - while (cond == EC_Normal && rsp.DimseStatus == STATUS_Pending && normal) { + while (cond == EC_Normal && rsp.DimseStatus == STATUS_MOVE_Pending_SubOperationsAreContinuing && normal) { responseCount++; cond = DIMSE_checkForCancelRQ(assoc, presIdCmd, request->MessageID); diff --git a/dcmnet/libsrc/dimstore.cc b/dcmnet/libsrc/dimstore.cc index 24189054..5db5ea88 100644 --- a/dcmnet/libsrc/dimstore.cc +++ b/dcmnet/libsrc/dimstore.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -406,7 +406,7 @@ DIMSE_storeProvider( T_ASC_Association *assoc, /* initialize the C-STORE-RSP message variable */ bzero((char*)&response, sizeof(response)); - response.DimseStatus = STATUS_Success; /* assume */ + response.DimseStatus = STATUS_STORE_Success; /* assume */ response.MessageIDBeingRespondedTo = request->MessageID; response.DataSetType = DIMSE_DATASET_NULL; /* always for C-STORE-RSP */ OFStandard::strlcpy(response.AffectedSOPClassUID, request->AffectedSOPClassUID, sizeof(response.AffectedSOPClassUID)); @@ -492,7 +492,7 @@ DIMSE_storeProvider( T_ASC_Association *assoc, /* depending on the error status, set the success indicating flag in the response message */ if (cond == EC_Normal) { - response.DimseStatus = STATUS_Success; + response.DimseStatus = STATUS_STORE_Success; } else if (cond == DIMSE_OUTOFRESOURCES) { response.DimseStatus = STATUS_STORE_Refused_OutOfResources; } else { diff --git a/dcmnet/libsrc/dul.cc b/dcmnet/libsrc/dul.cc index 526fe60f..b8e9cc04 100644 --- a/dcmnet/libsrc/dul.cc +++ b/dcmnet/libsrc/dul.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2019, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -1803,7 +1803,7 @@ receiveTransportConnectionTCP(PRIVATE_NETWORKKEY ** network, CloseHandle(hChildStdInWrite); // we need a STARTUPINFO and a PROCESS_INFORMATION structure for CreateProcess. - STARTUPINFO si; + STARTUPINFOA si; PROCESS_INFORMATION pi; memset(&pi,0,sizeof(pi)); memset(&si,0,sizeof(si)); @@ -1818,7 +1818,7 @@ receiveTransportConnectionTCP(PRIVATE_NETWORKKEY ** network, si.hStdInput = hChildStdInRead; // create child process. - if (!CreateProcess(NULL,OFconst_cast(char *, cmdLine.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) + if (!CreateProcessA(NULL,OFconst_cast(char *, cmdLine.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { OFOStringStream stream; stream << "Multi-Process Error: Creating process failed with error code " diff --git a/dcmnet/libsrc/dulfsm.cc b/dcmnet/libsrc/dulfsm.cc index e3facda6..91dcc7fc 100644 --- a/dcmnet/libsrc/dulfsm.cc +++ b/dcmnet/libsrc/dulfsm.cc @@ -313,7 +313,7 @@ findSCUSCPRole(LST_HEAD ** lst, char *abstractSyntax); void destroyPresentationContextList(LST_HEAD ** l); void destroyUserInformationLists(DUL_USERINFO * userInfo); -static FSM_Event_Description Event_Table[] = { +static volatile FSM_Event_Description Event_Table[] = { {A_ASSOCIATE_REQ_LOCAL_USER, "A-ASSOCIATE request (local user)"}, {TRANS_CONN_CONFIRM_LOCAL_USER, "Transport conn confirmation (local)"}, {A_ASSOCIATE_AC_PDU_RCV, "A-ASSOCIATE-AC PDU (on transport)"}, @@ -335,7 +335,7 @@ static FSM_Event_Description Event_Table[] = { {INVALID_PDU, "Unrecognized/invalid PDU"} }; -static FSM_FUNCTION FSM_FunctionTable[] = { +static volatile FSM_FUNCTION FSM_FunctionTable[] = { {AE_1, AE_1_TransportConnect, "AE 1 Transport Connect"}, {AE_2, AE_2_SendAssociateRQPDU, "AE 2 Send Associate RQ PDU"}, {AE_3, AE_3_AssociateConfirmationAccept, "AE 3 Associate Confirmation Accept"}, @@ -370,7 +370,7 @@ static FSM_FUNCTION FSM_FunctionTable[] = { {AR_10, AR_10_ConfirmRelease, "AR 10 Confirm Release"} }; -static FSM_ENTRY StateTable[DUL_NUMBER_OF_EVENTS][DUL_NUMBER_OF_STATES] = { +static volatile FSM_ENTRY StateTable[DUL_NUMBER_OF_EVENTS][DUL_NUMBER_OF_STATES] = { { // EVENT, STATE, ACTION, NEXT_STATE {A_ASSOCIATE_REQ_LOCAL_USER, STATE1, AE_1, STATE4, "", "", NULL}, @@ -750,7 +750,7 @@ PRV_StateMachine(PRIVATE_NETWORKKEY ** network, PRIVATE_ASSOCIATIONKEY ** association, int event, int state, void *params) { - FSM_ENTRY + volatile FSM_ENTRY * entry; /* check if the given event is valid, if not return an error */ @@ -777,8 +777,8 @@ PRV_StateMachine(PRIVATE_NETWORKKEY ** network, /* dump information if required */ DCMNET_TRACE("DUL FSM Table: State: " << state << " Event: " << event << OFendl - << "DUL Event: " << entry->eventName << OFendl - << "DUL Action: " << entry->actionName); + << "DUL Event: " << OFconst_cast(const char *, entry->eventName) << OFendl + << "DUL Action: " << OFconst_cast(const char *, entry->actionName)); /* if the state table's entry specifies an action function, execute this function and return */ /* it's result value. If there is no action function defined, return a corresponding error. */ @@ -3476,7 +3476,7 @@ readPDUHeadTCP(PRIVATE_ASSOCIATIONKEY ** association, { unsigned long length; - static unsigned char + static const unsigned char legalPDUTypes[] = { DUL_TYPEASSOCIATERQ, DUL_TYPEASSOCIATEAC, DUL_TYPEASSOCIATERJ, DUL_TYPEDATA, diff --git a/dcmnet/libsrc/dulparse.cc b/dcmnet/libsrc/dulparse.cc index 73185ad4..0a84f385 100644 --- a/dcmnet/libsrc/dulparse.cc +++ b/dcmnet/libsrc/dulparse.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1994-2018, OFFIS e.V. + * Copyright (C) 1994-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were partly developed by @@ -607,9 +607,10 @@ parseUserInfo(DUL_USERINFO * userInfo, ** Parse the buffer and extract the Max PDU structure. ** ** Parameter Dictionary: -** max The structure to hold the Max PDU -** buf The buffer that is to be parsed -** itemLength Length of structure extracted. +** max The structure to hold the Max PDU item +** buf The buffer that is to be parsed (input/output value) +** itemLength Length of structure extracted (output value) +** availData Number of bytes announced to be available for this sub item (input value) ** ** Return Values: ** @@ -636,6 +637,10 @@ parseMaxPDU(DUL_MAXLENGTH * max, unsigned char *buf, if (max->length != 4) DCMNET_WARN("Invalid length (" << max->length << ") for maximum length item, must be 4"); + // Is there less data than the length field claims there is? + if (availData - 4 < max->length) + return makeLengthError("Max PDU", availData, 0, max->length); + DCMNET_TRACE("Maximum PDU Length: " << (unsigned long)max->maxLength); return EC_Normal; @@ -692,8 +697,9 @@ parseDummy(unsigned char *buf, unsigned long *itemLength, unsigned long availDat ** ** Parameter Dictionary: ** role The structure to hold the SCU-SCP role list -** buf The buffer that is to be parsed -** itemLength Length of structure extracted. +** buf The buffer that is to be parsed (input/output value) +** itemLength Length of structure extracted (output value) +** availData Number of bytes announced to be available for this sub item (input value) ** ** Return Values: ** @@ -733,10 +739,16 @@ parseSCUSCPRole(PRV_SCUSCPROLE * role, unsigned char *buf, if (UIDLength > DICOM_UI_LENGTH) { DCMNET_WARN("Provided role SOP Class UID length " << UIDLength - << " is larger than maximum allowed UID length " << DICOM_UI_LENGTH << " (will use 64 bytes max)"); + << " is larger than maximum allowed UID length " << DICOM_UI_LENGTH << " (will use 64 bytes max)"); UIDLength = DICOM_UI_LENGTH; } - OFStandard::strlcpy(role->SOPClassUID, (char*)buf, UIDLength+1 /* +1 for 0-byte */); + + // The UID in the source buffer is not necessarily null terminated. Copy with memcpy + // and add a zero byte. We have already checked that there is enough data available + // in the source source buffer and enough space in the target buffer. + (void) memcpy(role->SOPClassUID, buf, UIDLength); + role->SOPClassUID[UIDLength] = '\0'; + buf += UIDLength; role->SCURole = *buf++; role->SCPRole = *buf++; @@ -755,12 +767,18 @@ parseSCUSCPRole(PRV_SCUSCPROLE * role, unsigned char *buf, ** Purpose: ** Parse the buffer and extract the extended negotiation item ** +** Parameter Dictionary: +** extNeg The structure to hold the extended negotiation item +** buf The buffer that is to be parsed (input/output value) +** itemLength Length of structure extracted (output value) +** availData Number of bytes announced to be available for this sub item (input value) +** ** Return Values: ** */ static OFCondition parseExtNeg(SOPClassExtendedNegotiationSubItem* extNeg, unsigned char *buf, - unsigned long *length, unsigned long availData) + unsigned long *length, unsigned long availData) { unsigned char *bufStart = buf; @@ -825,8 +843,8 @@ parseExtNeg(SOPClassExtendedNegotiationSubItem* extNeg, unsigned char *buf, * * @param pdu The name of the field or PDU which got an invalid length field. * @param bufSize The size of the buffer that we received. - * @param length The length as given by the length field. * @param minSize The minimum size that a 'pdu' has to have. + * @param length The length as given by the length field. */ static OFCondition makeLengthError(const char *pdu, unsigned long bufSize, unsigned long minSize, diff --git a/dcmnet/libsrc/scp.cc b/dcmnet/libsrc/scp.cc index e250de74..e5f57a53 100644 --- a/dcmnet/libsrc/scp.cc +++ b/dcmnet/libsrc/scp.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2009-2018, OFFIS e.V. + * Copyright (C) 2009-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -21,478 +21,536 @@ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/dcmnet/scp.h" -#include "dcmtk/dcmnet/assoc.h" #include "dcmtk/dcmdata/dcostrmf.h" /* for class DcmOutputFileStream */ +#include "dcmtk/dcmnet/assoc.h" +#include "dcmtk/dcmnet/scp.h" +#include "dcmtk/dcmtls/tlslayer.h" // ---------------------------------------------------------------------------- -DcmSCP::DcmSCP() : - m_assoc(NULL), - m_cfg() +DcmSCP::DcmSCP() +: m_network(NULL) +, m_assoc(NULL) +, m_cfg() { - OFStandard::initializeNetwork(); + OFStandard::initializeNetwork(); } // ---------------------------------------------------------------------------- DcmSCP::~DcmSCP() { - // If there is an open association, drop it and free memory (just to be sure...) - if (m_assoc) - { - dropAndDestroyAssociation(); - } + // If there is an open association, drop it and free memory (just to be sure...) + if (m_assoc) + { + dropAndDestroyAssociation(); + } + + // clean up network structure if initialized + if (m_network) + { + ASC_dropNetwork(&m_network); + } - OFStandard::shutdownNetwork(); + OFStandard::shutdownNetwork(); } // ---------------------------------------------------------------------------- DcmSCPConfig& DcmSCP::getConfig() { - return *m_cfg; + return *m_cfg; } // ---------------------------------------------------------------------------- OFCondition DcmSCP::setConfig(const DcmSCPConfig& config) { - if (isConnected()) - { - return NET_EC_AlreadyConnected; - } - m_cfg = DcmSharedSCPConfig( config ); - return EC_Normal; + if (isConnected()) + { + return NET_EC_AlreadyConnected; + } + m_cfg = DcmSharedSCPConfig(config); + return EC_Normal; } - // ---------------------------------------------------------------------------- -OFCondition DcmSCP::listen() +OFCondition DcmSCP::openListenPort() { - // make sure not to let dcmdata remove trailing blank padding or perform other - // manipulations. We want to see the real data. - dcmEnableAutomaticInputDataCorrection.set( OFFalse ); - OFCondition cond = EC_Normal; - // Make sure data dictionary is loaded. - if( !dcmDataDict.isDictionaryLoaded() ) - DCMNET_WARN("No data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); + // clean up network structure if already initialized + if (m_network) + { + ASC_dropNetwork(&m_network); + m_network = NULL; + } + + // make sure not to let dcmdata remove trailing blank padding or perform other + // manipulations. We want to see the real data. + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + + OFCondition cond = EC_Normal; + // Make sure data dictionary is loaded. + if (!dcmDataDict.isDictionaryLoaded()) + DCMNET_WARN("No data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); #ifndef DISABLE_PORT_PERMISSION_CHECK #ifdef HAVE_GETEUID - // If port is privileged we must be as well. - if( m_cfg->getPort() < 1024 && geteuid() != 0 ) - { - DCMNET_ERROR("No privileges to open this network port (" << m_cfg->getPort() << ")"); - return NET_EC_InsufficientPortPrivileges; - } + // If port is privileged we must be as well. + if (m_cfg->getPort() < 1024 && geteuid() != 0) + { + DCMNET_ERROR("No privileges to open this network port (" << m_cfg->getPort() << ")"); + return NET_EC_InsufficientPortPrivileges; + } #endif #endif - // Check whether current association profile is valid - OFString tmp; - OFCondition result = m_cfg->checkAssociationProfile(m_cfg->getActiveAssociationProfile(), tmp); - if (result.bad()) - return result; + // Check whether current association profile is valid + OFString tmp; + OFCondition result = m_cfg->checkAssociationProfile(m_cfg->getActiveAssociationProfile(), tmp); + if (result.bad()) + return result; - // Initialize network, i.e. create an instance of T_ASC_Network*. - T_ASC_Network *network = NULL; - cond = ASC_initializeNetwork( NET_ACCEPTOR, OFstatic_cast(int, m_cfg->getPort()), m_cfg->getACSETimeout(), &network ); - if( cond.bad() ) - return cond; + // Initialize network, i.e. create an instance of T_ASC_Network*. + cond = ASC_initializeNetwork(NET_ACCEPTOR, OFstatic_cast(int, m_cfg->getPort()), m_cfg->getACSETimeout(), &m_network); + if (cond.bad()) + { + m_network = NULL; + return cond; + } - // drop root privileges now and revert to the calling user id (if we are running as setuid root) - cond = OFStandard::dropPrivileges(); - if (cond.bad()) - { - DCMNET_ERROR("setuid() failed, maximum number of processes/threads for uid already running."); - return cond; - } - - // If we get to this point, the entire initialization process has been completed - // successfully. Now, we want to start handling all incoming requests. Since - // this activity is supposed to represent a server process, we do not want to - // terminate this activity (unless indicated by the stopAfterCurrentAssociation() - // or stopAfterConnectionTimeout() methods). - while( cond.good() ) - { - // Wait for an association and handle the requests of - // the calling applications correspondingly. - cond = waitForAssociationRQ(network); - - // Check whether we have a timeout - if (cond == DUL_NOASSOCIATIONREQUEST) + if (m_cfg->transportLayerEnabled()) { - // If a stop is requested, stop - if (stopAfterConnectionTimeout()) - { - cond = NET_EC_StopAfterConnectionTimeout; - break; - } - else + cond = ASC_setTransportLayer(m_network, m_cfg->getTransportLayer(), OFFalse /* Do not take over ownership */); + if (cond.bad()) { - // stay in loop - cond = EC_Normal; + DCMNET_ERROR("DcmSCP: Error setting secure transport layer: " << cond.text()); + return cond; } } - // Stop if SCP is told to stop after association was handled - else if (stopAfterCurrentAssociation()) + + // drop root privileges now and revert to the calling user id (if we are running as setuid root) + cond = OFStandard::dropPrivileges(); + if (cond.bad()) + { + DCMNET_ERROR("setuid() failed, maximum number of processes/threads for uid already running."); + return cond; + } + + return cond; +} + +// ---------------------------------------------------------------------------- + +OFCondition DcmSCP::acceptAssociations() +{ + if (m_network == NULL) + { + DCMNET_ERROR("network port not initialized, call DcmSCP::openListenPort() first."); + return EC_IllegalCall; + } + + OFCondition cond = EC_Normal; + + // At this point, the entire initialization process has been completed + // successfully. Now, we want to start handling all incoming requests. Since + // this activity is supposed to represent a server process, we do not want to + // terminate this activity (unless indicated by the stopAfterCurrentAssociation() + // or stopAfterConnectionTimeout() methods). + while (cond.good()) { - cond = NET_EC_StopAfterAssociation; - break; + // Wait for an association and handle the requests of + // the calling applications correspondingly. + cond = waitForAssociationRQ(m_network); + + // Check whether we have a timeout + if (cond == DUL_NOASSOCIATIONREQUEST) + { + // If a stop is requested, stop + if (stopAfterConnectionTimeout()) + { + cond = NET_EC_StopAfterConnectionTimeout; + break; + } + else + { + // stay in loop + cond = EC_Normal; + } + } + // Stop if SCP is told to stop after association was handled + else if (stopAfterCurrentAssociation()) + { + cond = NET_EC_StopAfterAssociation; + break; + } } - } - // Drop the network, i.e. free memory of T_ASC_Network* structure. This call - // is the counterpart of ASC_initializeNetwork(...) which was called above. - ASC_dropNetwork( &network ); - network = NULL; + // Drop the network, i.e. free memory of T_ASC_Network* structure. This call + // is the counterpart of ASC_initializeNetwork(...) which was called above. + ASC_dropNetwork(&m_network); + m_network = NULL; + + // return ok + return cond; +} + +// ---------------------------------------------------------------------------- - // return ok +OFCondition DcmSCP::listen() +{ + OFCondition cond = openListenPort(); + if (cond.good()) cond = acceptAssociations(); return cond; } // ---------------------------------------------------------------------------- void DcmSCP::findPresentationContext(const T_ASC_PresentationContextID presID, - OFString &abstractSyntax, - OFString &transferSyntax) -{ - transferSyntax.clear(); - abstractSyntax.clear(); - if (m_assoc == NULL) - return; - - DUL_PRESENTATIONCONTEXT *pc; - LST_HEAD **l; - - /* we look for a presentation context matching - * both abstract and transfer syntax - */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc) - { - if (presID == pc->presentationContextID) - { - if (pc->result == ASC_P_ACCEPTANCE) - { - // found a match - transferSyntax = pc->acceptedTransferSyntax; - abstractSyntax = pc->abstractSyntax; - } - break; - } - pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } -} - - -DUL_PRESENTATIONCONTEXT* DcmSCP::findPresentationContextID(LST_HEAD *head, + OFString& abstractSyntax, + OFString& transferSyntax) +{ + transferSyntax.clear(); + abstractSyntax.clear(); + if (m_assoc == NULL) + return; + + DUL_PRESENTATIONCONTEXT* pc; + LST_HEAD** l; + + /* we look for a presentation context matching + * both abstract and transfer syntax + */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc) + { + if (presID == pc->presentationContextID) + { + if (pc->result == ASC_P_ACCEPTANCE) + { + // found a match + transferSyntax = pc->acceptedTransferSyntax; + abstractSyntax = pc->abstractSyntax; + } + break; + } + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } +} + +DUL_PRESENTATIONCONTEXT* DcmSCP::findPresentationContextID(LST_HEAD* head, T_ASC_PresentationContextID presentationContextID) { - DUL_PRESENTATIONCONTEXT *pc; - LST_HEAD **l; - OFBool found = OFFalse; + DUL_PRESENTATIONCONTEXT* pc; + LST_HEAD** l; + OFBool found = OFFalse; - if (head == NULL) - return NULL; + if (head == NULL) + return NULL; - l = &head; - if (*l == NULL) - return NULL; + l = &head; + if (*l == NULL) + return NULL; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); - while (pc && !found) - { - if (pc->presentationContextID == presentationContextID) - { - found = OFTrue; - } else + while (pc && !found) { - pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); + if (pc->presentationContextID == presentationContextID) + { + found = OFTrue; + } + else + { + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } } - } - return pc; + return pc; } // ---------------------------------------------------------------------------- void DcmSCP::refuseAssociation(const DcmRefuseReasonType reason) { - if (m_assoc == NULL) - { - DCMNET_WARN("DcmSCP::refuseAssociation() called but actually no association running, ignoring"); - return; - } - - T_ASC_RejectParameters rej; - - // dump some information if required - switch( reason ) - { - case DCMSCP_TOO_MANY_ASSOCIATIONS: - DCMNET_INFO("Refusing Association (too many associations)"); - break; - case DCMSCP_CANNOT_FORK: - DCMNET_INFO("Refusing Association (cannot fork)"); - break; - case DCMSCP_BAD_APPLICATION_CONTEXT_NAME: - DCMNET_INFO("Refusing Association (bad application context)"); - break; - case DCMSCP_CALLING_HOST_NOT_ALLOWED: - DCMNET_INFO("Refusing Association (connecting host not allowed)"); - break; - case DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED: - DCMNET_INFO("Refusing Association (called AE title not recognized)"); - break; - case DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED: - DCMNET_INFO("Refusing Association (calling AE title not recognized)"); - break; - case DCMSCP_FORCED: - DCMNET_INFO("Refusing Association (forced via command line)"); - break; - case DCMSCP_NO_IMPLEMENTATION_CLASS_UID: - DCMNET_INFO("Refusing Association (no implementation class UID provided)"); - break; - case DCMSCP_NO_PRESENTATION_CONTEXTS: - DCMNET_INFO("Refusing Association (no acceptable presentation contexts)"); - break; - case DCMSCP_INTERNAL_ERROR: - DCMNET_INFO("Refusing Association (internal error)"); - break; - default: - DCMNET_INFO("Refusing Association (unknown reason)"); - break; - } - - // Set some values in the reject message depending on the reason - switch( reason ) - { - case DCMSCP_TOO_MANY_ASSOCIATIONS: - rej.result = ASC_RESULT_REJECTEDTRANSIENT; - rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED; - rej.reason = ASC_REASON_SP_PRES_LOCALLIMITEXCEEDED; - break; - case DCMSCP_CANNOT_FORK: - rej.result = ASC_RESULT_REJECTEDPERMANENT; - rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED; - rej.reason = ASC_REASON_SP_PRES_TEMPORARYCONGESTION; - break; - case DCMSCP_BAD_APPLICATION_CONTEXT_NAME: - rej.result = ASC_RESULT_REJECTEDTRANSIENT; - rej.source = ASC_SOURCE_SERVICEUSER; - rej.reason = ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED; - break; - case DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED: - rej.result = ASC_RESULT_REJECTEDPERMANENT; - rej.source = ASC_SOURCE_SERVICEUSER; - rej.reason = ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED; - break; - case DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED: - rej.result = ASC_RESULT_REJECTEDPERMANENT; - rej.source = ASC_SOURCE_SERVICEUSER; - rej.reason = ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED; - break; - case DCMSCP_FORCED: - case DCMSCP_NO_IMPLEMENTATION_CLASS_UID: - case DCMSCP_NO_PRESENTATION_CONTEXTS: - case DCMSCP_CALLING_HOST_NOT_ALLOWED: - case DCMSCP_INTERNAL_ERROR: - default: - rej.result = ASC_RESULT_REJECTEDPERMANENT; - rej.source = ASC_SOURCE_SERVICEUSER; - rej.reason = ASC_REASON_SU_NOREASON; - break; - } - - // Reject the association request. - ASC_rejectAssociation( m_assoc, &rej ); -} - -// ---------------------------------------------------------------------------- - -OFCondition DcmSCP::waitForAssociationRQ(T_ASC_Network *network) -{ - if (network == NULL) - return ASC_NULLKEY; - if (m_assoc != NULL) - return DIMSE_ILLEGALASSOCIATION; - - Uint32 timeout = m_cfg->getConnectionTimeout(); - - // Listen to a socket for timeout seconds and wait for an association request - OFCondition cond = ASC_receiveAssociation( network, &m_assoc, m_cfg->getMaxReceivePDULength(), NULL, NULL, OFFalse, - m_cfg->getConnectionBlockingMode(), OFstatic_cast(int, timeout) ); - - // In case of a timeout in non-blocking mode, call notifier (and return - // to main event loop later) - if ( cond == DUL_NOASSOCIATIONREQUEST ) - { - notifyConnectionTimeout(); - } - else - { - // If association could be received, handle it - if( cond.good() ) - { - cond = processAssociationRQ(); - // There was an association which has ended now: - // Call notifier and output separator line. - notifyAssociationTermination(); - DCMNET_DEBUG( "+++++++++++++++++++++++++++++" ); - } - // Else, if we could not receive an association request since there was - // some error, just ignore it (and continue in main event loop later) - else + if (m_assoc == NULL) { - DCMNET_ERROR("Could not receive association request: " << cond.text()); - cond = EC_Normal; + DCMNET_WARN("DcmSCP::refuseAssociation() called but actually no association running, ignoring"); + return; } - } - // We are done with this association, free it and set to NULL. - // ASC_receiveAssociation will always create a related structure, even - // if no association was received at all. - dropAndDestroyAssociation(); - return cond; + T_ASC_RejectParameters rej; + + // dump some information if required + switch (reason) + { + case DCMSCP_TOO_MANY_ASSOCIATIONS: + DCMNET_INFO("Refusing Association (too many associations)"); + break; + case DCMSCP_CANNOT_FORK: + DCMNET_INFO("Refusing Association (cannot fork)"); + break; + case DCMSCP_BAD_APPLICATION_CONTEXT_NAME: + DCMNET_INFO("Refusing Association (bad application context)"); + break; + case DCMSCP_CALLING_HOST_NOT_ALLOWED: + DCMNET_INFO("Refusing Association (connecting host not allowed)"); + break; + case DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED: + DCMNET_INFO("Refusing Association (called AE title not recognized)"); + break; + case DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED: + DCMNET_INFO("Refusing Association (calling AE title not recognized)"); + break; + case DCMSCP_FORCED: + DCMNET_INFO("Refusing Association (forced via command line)"); + break; + case DCMSCP_NO_IMPLEMENTATION_CLASS_UID: + DCMNET_INFO("Refusing Association (no implementation class UID provided)"); + break; + case DCMSCP_NO_PRESENTATION_CONTEXTS: + DCMNET_INFO("Refusing Association (no acceptable presentation contexts)"); + break; + case DCMSCP_INTERNAL_ERROR: + DCMNET_INFO("Refusing Association (internal error)"); + break; + default: + DCMNET_INFO("Refusing Association (unknown reason)"); + break; + } + + // Set some values in the reject message depending on the reason + switch (reason) + { + case DCMSCP_TOO_MANY_ASSOCIATIONS: + rej.result = ASC_RESULT_REJECTEDTRANSIENT; + rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED; + rej.reason = ASC_REASON_SP_PRES_LOCALLIMITEXCEEDED; + break; + case DCMSCP_CANNOT_FORK: + rej.result = ASC_RESULT_REJECTEDPERMANENT; + rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED; + rej.reason = ASC_REASON_SP_PRES_TEMPORARYCONGESTION; + break; + case DCMSCP_BAD_APPLICATION_CONTEXT_NAME: + rej.result = ASC_RESULT_REJECTEDTRANSIENT; + rej.source = ASC_SOURCE_SERVICEUSER; + rej.reason = ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED; + break; + case DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED: + rej.result = ASC_RESULT_REJECTEDPERMANENT; + rej.source = ASC_SOURCE_SERVICEUSER; + rej.reason = ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED; + break; + case DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED: + rej.result = ASC_RESULT_REJECTEDPERMANENT; + rej.source = ASC_SOURCE_SERVICEUSER; + rej.reason = ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED; + break; + case DCMSCP_FORCED: + case DCMSCP_NO_IMPLEMENTATION_CLASS_UID: + case DCMSCP_NO_PRESENTATION_CONTEXTS: + case DCMSCP_CALLING_HOST_NOT_ALLOWED: + case DCMSCP_INTERNAL_ERROR: + default: + rej.result = ASC_RESULT_REJECTEDPERMANENT; + rej.source = ASC_SOURCE_SERVICEUSER; + rej.reason = ASC_REASON_SU_NOREASON; + break; + } + + // Reject the association request. + ASC_rejectAssociation(m_assoc, &rej); } +// ---------------------------------------------------------------------------- + +OFCondition DcmSCP::waitForAssociationRQ(T_ASC_Network* network) +{ + if (network == NULL) + return ASC_NULLKEY; + if (m_assoc != NULL) + return DIMSE_ILLEGALASSOCIATION; + + Uint32 timeout = m_cfg->getConnectionTimeout(); + OFBool useSecureLayer = m_cfg->transportLayerEnabled(); + + // Listen to a socket for timeout seconds and wait for an association request + OFCondition cond = ASC_receiveAssociation(network, + &m_assoc, + m_cfg->getMaxReceivePDULength(), + NULL, + NULL, + useSecureLayer, + m_cfg->getConnectionBlockingMode(), + OFstatic_cast(int, timeout)); + + // In case of a timeout in non-blocking mode, call notifier (and return + // to main event loop later) + if (cond == DUL_NOASSOCIATIONREQUEST) + { + notifyConnectionTimeout(); + } + else + { + // If association could be received, handle it + if (cond.good()) + { + cond = processAssociationRQ(); + // There was an association which has ended now: + // Call notifier and output separator line. + notifyAssociationTermination(); + DCMNET_DEBUG("+++++++++++++++++++++++++++++"); + } + // Else, if we could not receive an association request since there was + // some error, just ignore it (and continue in main event loop later) + else + { + DCMNET_ERROR("Could not receive association request: " << cond.text()); + cond = EC_Normal; + } + } + + // We are done with this association, free it and set to NULL. + // ASC_receiveAssociation will always create a related structure, even + // if no association was received at all. + dropAndDestroyAssociation(); + return cond; +} OFCondition DcmSCP::processAssociationRQ() { - DcmSCPActionType desiredAction = DCMSCP_ACTION_UNDEFINED; - if ( (m_assoc == NULL) || (m_assoc->params == NULL) ) - return ASC_NULLKEY; + DcmSCPActionType desiredAction = DCMSCP_ACTION_UNDEFINED; + if ((m_assoc == NULL) || (m_assoc->params == NULL)) + return ASC_NULLKEY; - // call notifier function - notifyAssociationRequest(*m_assoc->params, desiredAction); - if (desiredAction != DCMSCP_ACTION_UNDEFINED) - { - if (desiredAction == DCMSCP_ACTION_REFUSE_ASSOCIATION) + // call notifier function + notifyAssociationRequest(*m_assoc->params, desiredAction); + if (desiredAction != DCMSCP_ACTION_UNDEFINED) { - refuseAssociation( DCMSCP_INTERNAL_ERROR ); - return EC_Normal; + if (desiredAction == DCMSCP_ACTION_REFUSE_ASSOCIATION) + { + refuseAssociation(DCMSCP_INTERNAL_ERROR); + return EC_Normal; + } + else + desiredAction = DCMSCP_ACTION_UNDEFINED; // reset for later use } - else desiredAction = DCMSCP_ACTION_UNDEFINED; // reset for later use - } - // Now we have to figure out if we might have to refuse the association request. - // This is the case if at least one of five conditions is met: + // Now we have to figure out if we might have to refuse the association request. + // This is the case if at least one of five conditions is met: - // Condition 1: if option "--refuse" is set we want to refuse the association request. - if( m_cfg->getRefuseAssociation() ) - { - refuseAssociation( DCMSCP_FORCED ); - return EC_Normal; - } - - // Condition 2: determine the application context name. If an error occurred or if the - // application context name is not supported we want to refuse the association request. - char buf[BUFSIZ]; - OFCondition cond = ASC_getApplicationContextName( m_assoc->params, buf , sizeof(buf)); - if( cond.bad() || strcmp( buf, DICOM_STDAPPLICATIONCONTEXT ) != 0 ) - { - refuseAssociation( DCMSCP_BAD_APPLICATION_CONTEXT_NAME ); - return EC_Normal; - } + // Condition 1: if option "--refuse" is set we want to refuse the association request. + if (m_cfg->getRefuseAssociation()) + { + refuseAssociation(DCMSCP_FORCED); + return EC_Normal; + } - // Condition 3: if the calling host is not supported, we want to refuse - // the association request - if (!checkCallingHostAccepted(m_assoc->params->DULparams.calledPresentationAddress)) - { - refuseAssociation( DCMSCP_CALLING_HOST_NOT_ALLOWED ); - return EC_Normal; - } + // Condition 2: determine the application context name. If an error occurred or if the + // application context name is not supported we want to refuse the association request. + char buf[BUFSIZ]; + OFCondition cond = ASC_getApplicationContextName(m_assoc->params, buf, sizeof(buf)); + if (cond.bad() || strcmp(buf, DICOM_STDAPPLICATIONCONTEXT) != 0) + { + refuseAssociation(DCMSCP_BAD_APPLICATION_CONTEXT_NAME); + return EC_Normal; + } - // Condition 4: if the calling or called application entity title is not supported - // we want to refuse the association request - if (!checkCalledAETitleAccepted(m_assoc->params->DULparams.calledAPTitle)) - { - refuseAssociation( DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED ); - return EC_Normal; - } + // Condition 3: if the calling host is not supported, we want to refuse + // the association request + if (!checkCallingHostAccepted(m_assoc->params->DULparams.calledPresentationAddress)) + { + refuseAssociation(DCMSCP_CALLING_HOST_NOT_ALLOWED); + return EC_Normal; + } - if (!checkCallingAETitleAccepted(m_assoc->params->DULparams.callingAPTitle)) - { - refuseAssociation( DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED ); - return EC_Normal; - } - - /* set our application entity title */ - if (m_cfg->getRespondWithCalledAETitle()) - ASC_setAPTitles(m_assoc->params, NULL, NULL, m_assoc->params->DULparams.calledAPTitle); - else - ASC_setAPTitles(m_assoc->params, NULL, NULL, m_cfg->getAETitle().c_str()); - - /* If we get to this point the association shall be negotiated. - Thus, for every presentation context it is checked whether - it can be accepted. However, this is only a "dry" run, i.e. - there is not yet sent a response message to the SCU - */ - cond = negotiateAssociation(); - if( cond.bad() ) - { - return EC_Normal; - } + // Condition 4: if the calling or called application entity title is not supported + // we want to refuse the association request + if (!checkCalledAETitleAccepted(m_assoc->params->DULparams.calledAPTitle)) + { + refuseAssociation(DCMSCP_CALLED_AE_TITLE_NOT_RECOGNIZED); + return EC_Normal; + } + + if (!checkCallingAETitleAccepted(m_assoc->params->DULparams.callingAPTitle)) + { + refuseAssociation(DCMSCP_CALLING_AE_TITLE_NOT_RECOGNIZED); + return EC_Normal; + } + + /* set our application entity title */ + if (m_cfg->getRespondWithCalledAETitle()) + ASC_setAPTitles(m_assoc->params, NULL, NULL, m_assoc->params->DULparams.calledAPTitle); + else + ASC_setAPTitles(m_assoc->params, NULL, NULL, m_cfg->getAETitle().c_str()); + + /* If we get to this point the association shall be negotiated. + Thus, for every presentation context it is checked whether + it can be accepted. However, this is only a "dry" run, i.e. + there is not yet sent a response message to the SCU + */ + cond = negotiateAssociation(); + if (cond.bad()) + { + return EC_Normal; + } + + // Reject association if no presentation context was negotiated + if (ASC_countAcceptedPresentationContexts(m_assoc->params) == 0) + { + // Dump some debug information + OFString tempStr; + DCMNET_INFO("No Acceptable Presentation Contexts"); + if (m_cfg->getVerbosePCMode()) + DCMNET_INFO(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RJ)); + else + DCMNET_DEBUG(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RJ)); + refuseAssociation(DCMSCP_NO_PRESENTATION_CONTEXTS); + return EC_Normal; + } + + // If the negotiation was successful, accept the association request + cond = ASC_acknowledgeAssociation(m_assoc); + if (cond.bad()) + { + return EC_Normal; + } + notifyAssociationAcknowledge(); - // Reject association if no presentation context was negotiated - if( ASC_countAcceptedPresentationContexts( m_assoc->params ) == 0 ) - { // Dump some debug information OFString tempStr; - DCMNET_INFO("No Acceptable Presentation Contexts"); + DCMNET_INFO("Association Acknowledged (Max Send PDV: " << OFstatic_cast(Uint32, m_assoc->sendPDVLength) << ")"); if (m_cfg->getVerbosePCMode()) - DCMNET_INFO(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RJ)); + DCMNET_INFO(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_AC)); else - DCMNET_DEBUG(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RJ)); - refuseAssociation( DCMSCP_NO_PRESENTATION_CONTEXTS ); - return EC_Normal; - } - - // If the negotiation was successful, accept the association request - cond = ASC_acknowledgeAssociation( m_assoc ); - if( cond.bad() ) - { - return EC_Normal; - } - notifyAssociationAcknowledge(); + DCMNET_DEBUG(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_AC)); - // Dump some debug information - OFString tempStr; - DCMNET_INFO("Association Acknowledged (Max Send PDV: " << OFstatic_cast(Uint32, m_assoc->sendPDVLength) << ")"); - if (m_cfg->getVerbosePCMode()) - DCMNET_INFO(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_AC)); - else - DCMNET_DEBUG(ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_AC)); + // Go ahead and handle the association (i.e. handle the caller's requests) in this process + handleAssociation(); - // Go ahead and handle the association (i.e. handle the caller's requests) in this process - handleAssociation(); - - return EC_Normal; + return EC_Normal; } // ---------------------------------------------------------------------------- OFCondition DcmSCP::negotiateAssociation() { - // Check whether there is something to negotiate... - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; + // Check whether there is something to negotiate... + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Set presentation contexts as defined in association configuration - OFCondition result = m_cfg->evaluateIncomingAssociation(*m_assoc); - if (result.bad()) - { - OFString tempStr; - DCMNET_ERROR(DimseCondition::dump(tempStr, result)); - } - return result; + // Set presentation contexts as defined in association configuration + OFCondition result = m_cfg->evaluateIncomingAssociation(*m_assoc); + if (result.bad()) + { + OFString tempStr; + DCMNET_ERROR(DimseCondition::dump(tempStr, result)); + } + return result; } // ---------------------------------------------------------------------------- @@ -503,18 +561,19 @@ OFCondition DcmSCP::abortAssociation() // Check whether there is an active association if (isConnected()) { - // Abort current association - DCMNET_INFO("Aborting Association (initiated by SCP)"); - cond = ASC_abortAssociation(m_assoc); - // Notify user in case of error - if (cond.bad()) - { - OFString tempStr; - DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); - } - // Note: association is dropped and memory freed somewhere else - } else - DCMNET_WARN("DcmSCP::abortAssociation() called but SCP actually has no association running, ignoring"); + // Abort current association + DCMNET_INFO("Aborting Association (initiated by SCP)"); + cond = ASC_abortAssociation(m_assoc); + // Notify user in case of error + if (cond.bad()) + { + OFString tempStr; + DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); + } + // Note: association is dropped and memory freed somewhere else + } + else + DCMNET_WARN("DcmSCP::abortAssociation() called but SCP actually has no association running, ignoring"); return cond; } @@ -522,889 +581,914 @@ OFCondition DcmSCP::abortAssociation() void DcmSCP::handleAssociation() { - if (m_assoc == NULL) - { - DCMNET_WARN("DcmSCP::handleAssociation() called but SCP actually has no association running, ignoring"); - return; - } - - // Receive a DIMSE command and perform all the necessary actions. (Note that ReceiveAndHandleCommands() - // will always return a value 'cond' for which 'cond.bad()' will be true. This value indicates that either - // some kind of error occurred, or that the peer aborted the association (DUL_PEERABORTEDASSOCIATION), - // or that the peer requested the release of the association (DUL_PEERREQUESTEDRELEASE).) (Also note - // that ReceiveAndHandleCommands() will never return EC_Normal.) - OFCondition cond = EC_Normal; - T_DIMSE_Message message; - T_ASC_PresentationContextID presID; - - // start a loop to be able to receive more than one DIMSE command - while( cond.good() ) - { - // receive a DIMSE command over the network - cond = DIMSE_receiveCommand( m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - &presID, &message, NULL ); - - // check if peer did release or abort, or if we have a valid message - if( cond.good() ) - { - DcmPresentationContextInfo presInfo; - getPresentationContextInfo(m_assoc, presID, presInfo); - cond = handleIncomingCommand(&message, presInfo); - } - } - // Clean up on association termination. - if( cond == DUL_PEERREQUESTEDRELEASE ) - { - notifyReleaseRequest(); - ASC_acknowledgeRelease(m_assoc); - } - else if( cond == DUL_PEERABORTEDASSOCIATION ) - { - notifyAbortRequest(); - } - else - { - notifyDIMSEError(cond); - ASC_abortAssociation( m_assoc ); - } -} - -// ---------------------------------------------------------------------------- - -OFCondition DcmSCP::handleIncomingCommand(T_DIMSE_Message *incomingMsg, - const DcmPresentationContextInfo &presInfo) -{ - OFCondition cond; - // Handle C-ECHO for Verification SOP Class - if ( (incomingMsg->CommandField == DIMSE_C_ECHO_RQ) - && (presInfo.abstractSyntax == UID_VerificationSOPClass) ) - { - // Process C-ECHO request - cond = handleECHORequest(incomingMsg->msg.CEchoRQ, presInfo.presentationContextID); - } else { - // We cannot handle this kind of message. Note that the condition will be returned - // and that the caller is responsible to end the association if desired. - OFString tempStr; - DCMNET_ERROR("Cannot handle this kind of DIMSE command (0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, incomingMsg->CommandField) << ")"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, *incomingMsg, DIMSE_INCOMING)); - cond = DIMSE_BADCOMMANDTYPE; - } - - // return result - return cond; + if (m_assoc == NULL) + { + DCMNET_WARN("DcmSCP::handleAssociation() called but SCP actually has no association running, ignoring"); + return; + } + + // Receive a DIMSE command and perform all the necessary actions. (Note that ReceiveAndHandleCommands() + // will always return a value 'cond' for which 'cond.bad()' will be true. This value indicates that either + // some kind of error occurred, or that the peer aborted the association (DUL_PEERABORTEDASSOCIATION), + // or that the peer requested the release of the association (DUL_PEERREQUESTEDRELEASE).) (Also note + // that ReceiveAndHandleCommands() will never return EC_Normal.) + OFCondition cond = EC_Normal; + T_DIMSE_Message message; + T_ASC_PresentationContextID presID; + + // start a loop to be able to receive more than one DIMSE command + while (cond.good()) + { + // receive a DIMSE command over the network + cond = DIMSE_receiveCommand( + m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), &presID, &message, NULL); + + // check if peer did release or abort, or if we have a valid message + if (cond.good()) + { + DcmPresentationContextInfo presInfo; + getPresentationContextInfo(m_assoc, presID, presInfo); + cond = handleIncomingCommand(&message, presInfo); + } + } + // Clean up on association termination. + if (cond == DUL_PEERREQUESTEDRELEASE) + { + notifyReleaseRequest(); + ASC_acknowledgeRelease(m_assoc); + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + notifyAbortRequest(); + } + else + { + notifyDIMSEError(cond); + ASC_abortAssociation(m_assoc); + } +} + +// ---------------------------------------------------------------------------- + +OFCondition DcmSCP::handleIncomingCommand(T_DIMSE_Message* incomingMsg, const DcmPresentationContextInfo& presInfo) +{ + OFCondition cond; + // Handle C-ECHO for Verification SOP Class + if ((incomingMsg->CommandField == DIMSE_C_ECHO_RQ) && (presInfo.abstractSyntax == UID_VerificationSOPClass)) + { + // Process C-ECHO request + cond = handleECHORequest(incomingMsg->msg.CEchoRQ, presInfo.presentationContextID); + } + else + { + // We cannot handle this kind of message. Note that the condition will be returned + // and that the caller is responsible to end the association if desired. + OFString tempStr; + DCMNET_ERROR("Cannot handle this kind of DIMSE command (0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, incomingMsg->CommandField) << ")"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, *incomingMsg, DIMSE_INCOMING)); + cond = DIMSE_BADCOMMANDTYPE; + } + + // return result + return cond; } // ---------------------------------------------------------------------------- // -- C-ECHO -- -OFCondition DcmSCP::handleECHORequest(T_DIMSE_C_EchoRQ &reqMessage, - const T_ASC_PresentationContextID presID) +OFCondition DcmSCP::handleECHORequest(T_DIMSE_C_EchoRQ& reqMessage, const T_ASC_PresentationContextID presID) { - OFCondition cond; - OFString tempStr; + OFCondition cond; + OFString tempStr; - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Received C-ECHO Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_INFO("Sending C-ECHO Response"); - } else { - DCMNET_INFO("Received C-ECHO Request (MsgID " << reqMessage.MessageID << ")"); - DCMNET_INFO("Sending C-ECHO Response (" << DU_cechoStatusString(STATUS_Success) << ")"); - } - - // Send response message - cond = DIMSE_sendEchoResponse( m_assoc, presID, &reqMessage, STATUS_Success, NULL ); - if( cond.bad() ) - DCMNET_ERROR("Cannot send C-ECHO Response: " << DimseCondition::dump(tempStr, cond)); - else - DCMNET_DEBUG("C-ECHO Response successfully sent"); + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-ECHO Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_INFO("Sending C-ECHO Response"); + } + else + { + DCMNET_INFO("Received C-ECHO Request (MsgID " << reqMessage.MessageID << ")"); + DCMNET_INFO("Sending C-ECHO Response (" << DU_cechoStatusString(STATUS_Success) << ")"); + } - return cond; + // Send response message + cond = DIMSE_sendEchoResponse(m_assoc, presID, &reqMessage, STATUS_Success, NULL); + if (cond.bad()) + DCMNET_ERROR("Cannot send C-ECHO Response: " << DimseCondition::dump(tempStr, cond)); + else + DCMNET_DEBUG("C-ECHO Response successfully sent"); + + return cond; } // ---------------------------------------------------------------------------- // -- C-STORE -- -OFCondition DcmSCP::handleSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, +OFCondition DcmSCP::handleSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset) + DcmDataset*& reqDataset) { - // First, receive the C-STORE request - OFCondition cond = receiveSTORERequest(reqMessage, presID, reqDataset); + // First, receive the C-STORE request + OFCondition cond = receiveSTORERequest(reqMessage, presID, reqDataset); - if (cond.good()) - { - // Then, check the request message and dataset and return an DIMSE status code - const Uint16 rspStatusCode = checkSTORERequest(reqMessage, reqDataset); - // ... that is sent back with the C-STORE response message - cond = sendSTOREResponse(presID, reqMessage, rspStatusCode); - } + if (cond.good()) + { + // Then, check the request message and dataset and return an DIMSE status code + const Uint16 rspStatusCode = checkSTORERequest(reqMessage, reqDataset); + // ... that is sent back with the C-STORE response message + cond = sendSTOREResponse(presID, reqMessage, rspStatusCode); + } - return cond; + return cond; } - -OFCondition DcmSCP::receiveSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, +OFCondition DcmSCP::receiveSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presIDdset; - // Remember the passed dataset pointer - DcmDataset *dataset = reqDataset; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received C-STORE Request"); - else - DCMNET_INFO("Received C-STORE Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received C-STORE request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset (in memory) - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive C-STORE dataset on presentation context " << OFstatic_cast(unsigned int, presID)); - return cond; - } + DcmDataset*& reqDataset) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Output request message only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presIDdset; + // Remember the passed dataset pointer + DcmDataset* dataset = reqDataset; + + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received C-STORE Request"); + else + DCMNET_INFO("Received C-STORE Request (MsgID " << reqMessage.MessageID << ")"); - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - if (dataset != reqDataset) + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) { - // Free memory allocated by receiveDIMSEDataset() - delete dataset; + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received C-STORE request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; } - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } - // Set return value - reqDataset = dataset; + // Receive dataset (in memory) + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive C-STORE dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return cond; + } - return cond; -} + // Output request message only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + if (dataset != reqDataset) + { + // Free memory allocated by receiveDIMSEDataset() + delete dataset; + } + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + + // Set return value + reqDataset = dataset; -OFCondition DcmSCP::receiveSTORERequest(T_DIMSE_C_StoreRQ &reqMessage, - const T_ASC_PresentationContextID presID, - const OFString &filename) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - // Use presentation context ID of the command set as a default - T_ASC_PresentationContextID presIDdset = presID; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received C-STORE Request"); - else - DCMNET_INFO("Received C-STORE Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received C-STORE request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset (directly to file) - cond = receiveSTORERequestDataset(&presIDdset, reqMessage, filename); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive C-STORE dataset on presentation context " << OFstatic_cast(unsigned int, presID)); return cond; - } +} - // Output request message only if trace level is enabled - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); +OFCondition DcmSCP::receiveSTORERequest(T_DIMSE_C_StoreRQ& reqMessage, + const T_ASC_PresentationContextID presID, + const OFString& filename) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } + OFCondition cond; + OFString tempStr; + // Use presentation context ID of the command set as a default + T_ASC_PresentationContextID presIDdset = presID; - return cond; -} + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received C-STORE Request"); + else + DCMNET_INFO("Received C-STORE Request (MsgID " << reqMessage.MessageID << ")"); + + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received C-STORE request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } + + // Receive dataset (directly to file) + cond = receiveSTORERequestDataset(&presIDdset, reqMessage, filename); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive C-STORE dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return cond; + } + + // Output request message only if trace level is enabled + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + return cond; +} OFCondition DcmSCP::sendSTOREResponse(const T_ASC_PresentationContextID presID, - const T_DIMSE_C_StoreRQ &reqMessage, + const T_DIMSE_C_StoreRQ& reqMessage, const Uint16 rspStatusCode) { - // Call the method doing the real work - return sendSTOREResponse(presID, reqMessage.MessageID, reqMessage.AffectedSOPClassUID, reqMessage.AffectedSOPInstanceUID, - rspStatusCode, NULL /* statusDetail */); + // Call the method doing the real work + return sendSTOREResponse(presID, + reqMessage.MessageID, + reqMessage.AffectedSOPClassUID, + reqMessage.AffectedSOPInstanceUID, + rspStatusCode, + NULL /* statusDetail */); } - OFCondition DcmSCP::sendSTOREResponse(const T_ASC_PresentationContextID presID, const Uint16 messageID, - const OFString &sopClassUID, - const OFString &sopInstanceUID, + const OFString& sopClassUID, + const OFString& sopInstanceUID, const Uint16 rspStatusCode, - DcmDataset *statusDetail) -{ - OFCondition cond; - OFString tempStr; - - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_C_StoreRSP &storeRsp = response.msg.CStoreRSP; - response.CommandField = DIMSE_C_STORE_RSP; - storeRsp.MessageIDBeingRespondedTo = messageID; - storeRsp.DimseStatus = rspStatusCode; - storeRsp.DataSetType = DIMSE_DATASET_NULL; - // Always send the optional fields "Affected SOP Class UID" and "Affected SOP Instance UID" - storeRsp.opts = O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID; - OFStandard::strlcpy(storeRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(storeRsp.AffectedSOPClassUID)); - OFStandard::strlcpy(storeRsp.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(storeRsp.AffectedSOPInstanceUID)); - - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-STORE Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); - } else { - DCMNET_INFO("Sending C-STORE Response (" << DU_cstoreStatusString(rspStatusCode) << ")"); - } - - // Send response message - cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */, statusDetail); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-STORE response: " << DimseCondition::dump(tempStr, cond)); - } + DcmDataset* statusDetail) +{ + OFCondition cond; + OFString tempStr; - return cond; -} + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_C_StoreRSP& storeRsp = response.msg.CStoreRSP; + response.CommandField = DIMSE_C_STORE_RSP; + storeRsp.MessageIDBeingRespondedTo = messageID; + storeRsp.DimseStatus = rspStatusCode; + storeRsp.DataSetType = DIMSE_DATASET_NULL; + // Always send the optional fields "Affected SOP Class UID" and "Affected SOP Instance UID" + storeRsp.opts = O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID; + OFStandard::strlcpy(storeRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(storeRsp.AffectedSOPClassUID)); + OFStandard::strlcpy( + storeRsp.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(storeRsp.AffectedSOPInstanceUID)); + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-STORE Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); + } + else + { + DCMNET_INFO("Sending C-STORE Response (" << DU_cstoreStatusString(rspStatusCode) << ")"); + } + + // Send response message + cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */, statusDetail); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-STORE response: " << DimseCondition::dump(tempStr, cond)); + } -Uint16 DcmSCP::checkSTORERequest(T_DIMSE_C_StoreRQ & /*reqMessage*/, - DcmDataset * /*reqDataset*/) + return cond; +} + +Uint16 DcmSCP::checkSTORERequest(T_DIMSE_C_StoreRQ& /*reqMessage*/, DcmDataset* /*reqDataset*/) { - // we default to success - return STATUS_Success; + // we default to success + return STATUS_Success; } // ---------------------------------------------------------------------------- // -- C-FIND -- -OFCondition DcmSCP::receiveFINDRequest(T_DIMSE_C_FindRQ &reqMessage, +OFCondition DcmSCP::receiveFINDRequest(T_DIMSE_C_FindRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presIDdset; - DcmDataset *dataset = NULL; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received C-FIND Request"); - else - DCMNET_INFO("Received C-FIND Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received C-FIND request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive C-FIND dataset on presentation context " << OFstatic_cast(unsigned int, presID)); - return DIMSE_BADDATA; - } - - // Output request message only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DcmDataset*& reqDataset) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - delete dataset; - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presIDdset; + DcmDataset* dataset = NULL; - // Set return value - reqDataset = dataset; + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received C-FIND Request"); + else + DCMNET_INFO("Received C-FIND Request (MsgID " << reqMessage.MessageID << ")"); - return cond; -} + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received C-FIND request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } + + // Receive dataset + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive C-FIND dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return DIMSE_BADDATA; + } + // Output request message only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + delete dataset; + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + + // Set return value + reqDataset = dataset; + + return cond; +} OFCondition DcmSCP::sendFINDResponse(const T_ASC_PresentationContextID presID, const Uint16 messageID, - const OFString &sopClassUID, - DcmDataset *rspDataset, + const OFString& sopClassUID, + DcmDataset* rspDataset, const Uint16 rspStatusCode, DcmDataset* statusDetail) { - OFCondition cond; - OFString tempStr; - - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_C_FindRSP &findRsp = response.msg.CFindRSP; - response.CommandField = DIMSE_C_FIND_RSP; - findRsp.MessageIDBeingRespondedTo = messageID; - findRsp.DimseStatus = rspStatusCode; - // Always send (the optional) field "Affected SOP Class UID" - findRsp.opts = O_FIND_AFFECTEDSOPCLASSUID; - OFStandard::strlcpy(findRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(findRsp.AffectedSOPClassUID)); - - if (rspDataset) - findRsp.DataSetType = DIMSE_DATASET_PRESENT; - else - findRsp.DataSetType = DIMSE_DATASET_NULL; - - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-FIND Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, rspDataset, presID)); - } else { - DCMNET_INFO("Sending C-FIND Response (" << DU_cfindStatusString(rspStatusCode) << ")"); - } - - // Send response message with dataset - cond = sendDIMSEMessage(presID, &response, rspDataset /* dataObject */, statusDetail); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-FIND response: " << DimseCondition::dump(tempStr, cond)); + OFCondition cond; + OFString tempStr; + + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_C_FindRSP& findRsp = response.msg.CFindRSP; + response.CommandField = DIMSE_C_FIND_RSP; + findRsp.MessageIDBeingRespondedTo = messageID; + findRsp.DimseStatus = rspStatusCode; + // Always send (the optional) field "Affected SOP Class UID" + findRsp.opts = O_FIND_AFFECTEDSOPCLASSUID; + OFStandard::strlcpy(findRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(findRsp.AffectedSOPClassUID)); + + if (rspDataset) + findRsp.DataSetType = DIMSE_DATASET_PRESENT; + else + findRsp.DataSetType = DIMSE_DATASET_NULL; + + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-FIND Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, rspDataset, presID)); + } + else + { + DCMNET_INFO("Sending C-FIND Response (" << DU_cfindStatusString(rspStatusCode) << ")"); + } + + // Send response message with dataset + cond = sendDIMSEMessage(presID, &response, rspDataset /* dataObject */, statusDetail); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-FIND response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } return cond; - } - return cond; } - -OFCondition DcmSCP::checkForCANCEL(T_ASC_PresentationContextID presID, - const Uint16 messageID) +OFCondition DcmSCP::checkForCANCEL(T_ASC_PresentationContextID presID, const Uint16 messageID) { - return DIMSE_checkForCancelRQ(m_assoc, presID, messageID); + return DIMSE_checkForCancelRQ(m_assoc, presID, messageID); } // ---------------------------------------------------------------------------- // -- C-MOVE -- -OFCondition DcmSCP::receiveMOVERequest(T_DIMSE_C_MoveRQ &reqMessage, +OFCondition DcmSCP::receiveMOVERequest(T_DIMSE_C_MoveRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - OFString &moveDest) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presIDdset; - DcmDataset *dataset = NULL; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received C-MOVE Request"); - else - DCMNET_INFO("Received C-MOVE Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received C-MOVE request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive C-MOVE dataset on presentation context " << OFstatic_cast(unsigned int, presID)); - return DIMSE_BADDATA; - } - - // Output request message only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DcmDataset*& reqDataset, + OFString& moveDest) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - delete dataset; - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presIDdset; + DcmDataset* dataset = NULL; - // Set return values - reqDataset = dataset; - moveDest = reqMessage.MoveDestination; + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received C-MOVE Request"); + else + DCMNET_INFO("Received C-MOVE Request (MsgID " << reqMessage.MessageID << ")"); - return cond; -} + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received C-MOVE request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } + + // Receive dataset + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive C-MOVE dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return DIMSE_BADDATA; + } + // Output request message only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + delete dataset; + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + + // Set return values + reqDataset = dataset; + moveDest = reqMessage.MoveDestination; + + return cond; +} OFCondition DcmSCP::sendMOVEResponse(const T_ASC_PresentationContextID presID, const Uint16 messageID, - const OFString &sopClassUID, - DcmDataset *rspDataset, + const OFString& sopClassUID, + DcmDataset* rspDataset, const Uint16 rspStatusCode, - DcmDataset *statusDetail, + DcmDataset* statusDetail, const Uint16 numRemain, const Uint16 numComplete, const Uint16 numFail, const Uint16 numWarn) { - OFCondition cond; - OFString tempStr; - - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_C_MoveRSP &moveRsp = response.msg.CMoveRSP; - response.CommandField = DIMSE_C_MOVE_RSP; - moveRsp.MessageIDBeingRespondedTo = messageID; - moveRsp.DimseStatus = rspStatusCode; - // Always send the optional field "Affected SOP Class UID" - moveRsp.opts = O_MOVE_AFFECTEDSOPCLASSUID; - OFStandard::strlcpy(moveRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(moveRsp.AffectedSOPClassUID)); - // Only send the other optional fields if needed - if ( (numRemain != 0) || (numComplete != 0) || (numFail != 0) || (numWarn != 0) ) - { - moveRsp.NumberOfRemainingSubOperations = numRemain; - moveRsp.NumberOfCompletedSubOperations = numComplete; - moveRsp.NumberOfFailedSubOperations = numFail; - moveRsp.NumberOfWarningSubOperations = numWarn; - moveRsp.opts |= O_MOVE_NUMBEROFREMAININGSUBOPERATIONS | O_MOVE_NUMBEROFCOMPLETEDSUBOPERATIONS | - O_MOVE_NUMBEROFFAILEDSUBOPERATIONS | O_MOVE_NUMBEROFWARNINGSUBOPERATIONS; - } - - if (rspDataset) - moveRsp.DataSetType = DIMSE_DATASET_PRESENT; - else - moveRsp.DataSetType = DIMSE_DATASET_NULL; - - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-MOVE Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, rspDataset, presID)); - } else { - DCMNET_INFO("Sending C-MOVE Response (" << DU_cmoveStatusString(rspStatusCode) << ")"); - } - - // Send response message with dataset - cond = sendDIMSEMessage(presID, &response, rspDataset /* dataObject */, statusDetail); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-MOVE response: " << DimseCondition::dump(tempStr, cond)); - } + OFCondition cond; + OFString tempStr; - return cond; + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_C_MoveRSP& moveRsp = response.msg.CMoveRSP; + response.CommandField = DIMSE_C_MOVE_RSP; + moveRsp.MessageIDBeingRespondedTo = messageID; + moveRsp.DimseStatus = rspStatusCode; + // Always send the optional field "Affected SOP Class UID" + moveRsp.opts = O_MOVE_AFFECTEDSOPCLASSUID; + OFStandard::strlcpy(moveRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(moveRsp.AffectedSOPClassUID)); + // Only send the other optional fields if needed + if ((numRemain != 0) || (numComplete != 0) || (numFail != 0) || (numWarn != 0)) + { + moveRsp.NumberOfRemainingSubOperations = numRemain; + moveRsp.NumberOfCompletedSubOperations = numComplete; + moveRsp.NumberOfFailedSubOperations = numFail; + moveRsp.NumberOfWarningSubOperations = numWarn; + moveRsp.opts |= O_MOVE_NUMBEROFREMAININGSUBOPERATIONS | O_MOVE_NUMBEROFCOMPLETEDSUBOPERATIONS + | O_MOVE_NUMBEROFFAILEDSUBOPERATIONS | O_MOVE_NUMBEROFWARNINGSUBOPERATIONS; + } + + if (rspDataset) + moveRsp.DataSetType = DIMSE_DATASET_PRESENT; + else + moveRsp.DataSetType = DIMSE_DATASET_NULL; + + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-MOVE Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, rspDataset, presID)); + } + else + { + DCMNET_INFO("Sending C-MOVE Response (" << DU_cmoveStatusString(rspStatusCode) << ")"); + } + + // Send response message with dataset + cond = sendDIMSEMessage(presID, &response, rspDataset /* dataObject */, statusDetail); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-MOVE response: " << DimseCondition::dump(tempStr, cond)); + } + + return cond; } // ---------------------------------------------------------------------------- // -- N-ACTION -- -OFCondition DcmSCP::receiveACTIONRequest(T_DIMSE_N_ActionRQ &reqMessage, +OFCondition DcmSCP::receiveACTIONRequest(T_DIMSE_N_ActionRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - Uint16 &actionTypeID) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presIDdset; - DcmDataset *dataset = NULL; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received N-ACTION Request"); - else - DCMNET_INFO("Received N-ACTION Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received N-ACTION request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive N-ACTION dataset on presentation context " << OFstatic_cast(unsigned int, presID)); - return DIMSE_BADDATA; - } - - // Output request message only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DcmDataset*& reqDataset, + Uint16& actionTypeID) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presIDdset; + DcmDataset* dataset = NULL; - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - delete dataset; - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received N-ACTION Request"); + else + DCMNET_INFO("Received N-ACTION Request (MsgID " << reqMessage.MessageID << ")"); - // Set return values - reqDataset = dataset; - actionTypeID = reqMessage.ActionTypeID; + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received N-ACTION request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } - return cond; -} + // Receive dataset + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive N-ACTION dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return DIMSE_BADDATA; + } + + // Output request message only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + delete dataset; + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + + // Set return values + reqDataset = dataset; + actionTypeID = reqMessage.ActionTypeID; + return cond; +} OFCondition DcmSCP::sendACTIONResponse(const T_ASC_PresentationContextID presID, const Uint16 messageID, - const OFString &sopClassUID, - const OFString &sopInstanceUID, + const OFString& sopClassUID, + const OFString& sopInstanceUID, const Uint16 rspStatusCode) { - OFCondition cond; - OFString tempStr; - - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_N_ActionRSP &actionRsp = response.msg.NActionRSP; - response.CommandField = DIMSE_N_ACTION_RSP; - actionRsp.MessageIDBeingRespondedTo = messageID; - actionRsp.DimseStatus = rspStatusCode; - actionRsp.DataSetType = DIMSE_DATASET_NULL; - // Always send the optional fields "Affected SOP Class UID" and "Affected SOP Instance UID" - actionRsp.opts = O_NACTION_AFFECTEDSOPCLASSUID | O_NACTION_AFFECTEDSOPINSTANCEUID; - OFStandard::strlcpy(actionRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(actionRsp.AffectedSOPClassUID)); - OFStandard::strlcpy(actionRsp.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(actionRsp.AffectedSOPInstanceUID)); - // Do not send any other optional fields, e.g. "Action Type ID" - - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-ACTION Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); - } else { - DCMNET_INFO("Sending N-ACTION Response (" << DU_nactionStatusString(rspStatusCode) << ")"); - } - - // Send response message - cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-ACTION response: " << DimseCondition::dump(tempStr, cond)); - } + OFCondition cond; + OFString tempStr; - return cond; + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_N_ActionRSP& actionRsp = response.msg.NActionRSP; + response.CommandField = DIMSE_N_ACTION_RSP; + actionRsp.MessageIDBeingRespondedTo = messageID; + actionRsp.DimseStatus = rspStatusCode; + actionRsp.DataSetType = DIMSE_DATASET_NULL; + // Always send the optional fields "Affected SOP Class UID" and "Affected SOP Instance UID" + actionRsp.opts = O_NACTION_AFFECTEDSOPCLASSUID | O_NACTION_AFFECTEDSOPINSTANCEUID; + OFStandard::strlcpy(actionRsp.AffectedSOPClassUID, sopClassUID.c_str(), sizeof(actionRsp.AffectedSOPClassUID)); + OFStandard::strlcpy( + actionRsp.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(actionRsp.AffectedSOPInstanceUID)); + // Do not send any other optional fields, e.g. "Action Type ID" + + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending N-ACTION Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); + } + else + { + DCMNET_INFO("Sending N-ACTION Response (" << DU_nactionStatusString(rspStatusCode) << ")"); + } + + // Send response message + cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-ACTION response: " << DimseCondition::dump(tempStr, cond)); + } + + return cond; } // ---------------------------------------------------------------------------- // -- N-EVENT-REPORT -- -OFCondition DcmSCP::handleEVENTREPORTRequest(T_DIMSE_N_EventReportRQ &reqMessage, +OFCondition DcmSCP::handleEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& reqMessage, const T_ASC_PresentationContextID presID, - DcmDataset *&reqDataset, - Uint16 &eventTypeID) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presIDdset; - DcmDataset *dataset = NULL; - // DcmDataset *statusDetail = NULL; // TODO: do we need this and if so, how do we get it? - Uint16 rspStatusCode = 0; - - // Dump debug information - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_INFO("Received N-EVENT-REPORT Request"); - else - DCMNET_INFO("Received N-EVENT-REPORT Request (MsgID " << reqMessage.MessageID << ")"); - - // Check if dataset is announced correctly - if (reqMessage.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received N-EVENT-REPORT request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Unable to receive N-EVENT-REPORT dataset on presentation context " << OFstatic_cast(unsigned int, presID)); - return DIMSE_BADDATA; - } - - // Output dataset only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DcmDataset*& reqDataset, + Uint16& eventTypeID) +{ + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differs"); - delete dataset; - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } - - // Check the request message and dataset and return the DIMSE status code to be used - rspStatusCode = checkEVENTREPORTRequest(reqMessage, dataset); - - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_N_EventReportRSP &eventReportRsp = response.msg.NEventReportRSP; - response.CommandField = DIMSE_N_EVENT_REPORT_RSP; - eventReportRsp.MessageIDBeingRespondedTo = reqMessage.MessageID; - eventReportRsp.DimseStatus = rspStatusCode; - eventReportRsp.DataSetType = DIMSE_DATASET_NULL; - // Do not send any optional fields - eventReportRsp.opts = 0; - eventReportRsp.AffectedSOPClassUID[0] = 0; - eventReportRsp.AffectedSOPInstanceUID[0] = 0; - - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-EVENT-REPORT Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); - } else { - DCMNET_INFO("Sending N-EVENT-REPORT Response (" << DU_neventReportStatusString(rspStatusCode) << ")"); - } - // Send response message - cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-EVENT-REPORT response: " << DimseCondition::dump(tempStr, cond)); - delete dataset; - return cond; - } + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presIDdset; + DcmDataset* dataset = NULL; + // DcmDataset *statusDetail = NULL; // TODO: do we need this and if so, how do we get it? + Uint16 rspStatusCode = 0; - // Set return values - reqDataset = dataset; - eventTypeID = reqMessage.EventTypeID; + // Dump debug information + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_INFO("Received N-EVENT-REPORT Request"); + else + DCMNET_INFO("Received N-EVENT-REPORT Request (MsgID " << reqMessage.MessageID << ")"); - return cond; -} + // Check if dataset is announced correctly + if (reqMessage.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received N-EVENT-REPORT request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } + // Receive dataset + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Unable to receive N-EVENT-REPORT dataset on presentation context " + << OFstatic_cast(unsigned int, presID)); + return DIMSE_BADDATA; + } -OFCondition DcmSCP::sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, - const Uint16 messageID, - const Uint16 eventTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode) -{ - // Do some basic validity checks - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - if (sopInstanceUID.empty() || (reqDataset == NULL)) - return DIMSE_NULLKEY; - - // Prepare DIMSE data structures for issuing request - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message request; - // Make sure everything is zeroed (especially options) - bzero((char*)&request, sizeof(request)); - T_DIMSE_N_EventReportRQ &eventReportReq = request.msg.NEventReportRQ; - DcmDataset *statusDetail = NULL; - - request.CommandField = DIMSE_N_EVENT_REPORT_RQ; - - // Generate a new message ID (?) - eventReportReq.MessageID = messageID; - - eventReportReq.DataSetType = DIMSE_DATASET_PRESENT; - eventReportReq.EventTypeID = eventTypeID; - - // Determine SOP Class from presentation context - OFString abstractSyntax, transferSyntax; - - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(eventReportReq.AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(eventReportReq.AffectedSOPClassUID)); - OFStandard::strlcpy(eventReportReq.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(eventReportReq.AffectedSOPInstanceUID)); - - // Send request - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-EVENT-REPORT Request"); // Output dataset only if trace level is enabled if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, dataset, presID)); else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &request, reqDataset); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-EVENT-REPORT request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } - // Receive response - T_DIMSE_Message response; - cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); - if (cond.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, reqMessage, DIMSE_INCOMING, NULL, presID)); + + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differs"); + delete dataset; + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } + + // Check the request message and dataset and return the DIMSE status code to be used + rspStatusCode = checkEVENTREPORTRequest(reqMessage, dataset); + + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_N_EventReportRSP& eventReportRsp = response.msg.NEventReportRSP; + response.CommandField = DIMSE_N_EVENT_REPORT_RSP; + eventReportRsp.MessageIDBeingRespondedTo = reqMessage.MessageID; + eventReportRsp.DimseStatus = rspStatusCode; + eventReportRsp.DataSetType = DIMSE_DATASET_NULL; + // Do not send any optional fields + eventReportRsp.opts = 0; + eventReportRsp.AffectedSOPClassUID[0] = 0; + eventReportRsp.AffectedSOPInstanceUID[0] = 0; - // Check command set - if (response.CommandField == DIMSE_N_EVENT_REPORT_RSP) - { if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { - DCMNET_INFO("Received N-EVENT-REPORT Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received N-EVENT-REPORT Response (" << DU_neventReportStatusString(response.msg.NEventReportRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected N-EVENT-REPORT response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, response.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } - - // Set return value - T_DIMSE_N_EventReportRSP &eventReportRsp = response.msg.NEventReportRSP; - rspStatusCode = eventReportRsp.DimseStatus; - - // Check whether there is a dataset to be received - if (eventReportRsp.DataSetType == DIMSE_DATASET_PRESENT) - { - // this should never happen - DcmDataset *tempDataset = NULL; - T_ASC_PresentationContextID tempID; - // Receive dataset - cond = receiveDIMSEDataset(&tempID, &tempDataset); - if (cond.good()) + DCMNET_INFO("Sending N-EVENT-REPORT Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); + } + else { - DCMNET_WARN("Received unexpected dataset after N-EVENT-REPORT response, ignoring"); - delete tempDataset; - } else { - DCMNET_ERROR("Failed receiving unexpected dataset after N-EVENT-REPORT response: " - << DimseCondition::dump(tempStr, cond)); - return DIMSE_BADDATA; + DCMNET_INFO("Sending N-EVENT-REPORT Response (" << DU_neventReportStatusString(rspStatusCode) << ")"); + } + // Send response message + cond = sendDIMSEMessage(presID, &response, NULL /* dataObject */); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-EVENT-REPORT response: " << DimseCondition::dump(tempStr, cond)); + delete dataset; + return cond; } - } - // Check whether the message ID being responded to is equal to the message ID of the request - if (eventReportRsp.MessageIDBeingRespondedTo != eventReportReq.MessageID) - { - DCMNET_ERROR("Received response with wrong message ID (" << eventReportRsp.MessageIDBeingRespondedTo - << " instead of " << eventReportReq.MessageID << ")"); - return DIMSE_BADMESSAGE; - } + // Set return values + reqDataset = dataset; + eventTypeID = reqMessage.EventTypeID; - return cond; + return cond; } - -Uint16 DcmSCP::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ & /*reqMessage*/, - DcmDataset * /*reqDataset*/) +OFCondition DcmSCP::sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, + const OFString& sopInstanceUID, + const Uint16 messageID, + const Uint16 eventTypeID, + DcmDataset* reqDataset, + Uint16& rspStatusCode) { - // we default to success - return STATUS_Success; + // Do some basic validity checks + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + if (sopInstanceUID.empty() || (reqDataset == NULL)) + return DIMSE_NULLKEY; + + // Prepare DIMSE data structures for issuing request + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message request; + // Make sure everything is zeroed (especially options) + bzero((char*)&request, sizeof(request)); + T_DIMSE_N_EventReportRQ& eventReportReq = request.msg.NEventReportRQ; + DcmDataset* statusDetail = NULL; + + request.CommandField = DIMSE_N_EVENT_REPORT_RQ; + + // Generate a new message ID (?) + eventReportReq.MessageID = messageID; + + eventReportReq.DataSetType = DIMSE_DATASET_PRESENT; + eventReportReq.EventTypeID = eventTypeID; + + // Determine SOP Class from presentation context + OFString abstractSyntax, transferSyntax; + + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy( + eventReportReq.AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(eventReportReq.AffectedSOPClassUID)); + OFStandard::strlcpy( + eventReportReq.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(eventReportReq.AffectedSOPInstanceUID)); + + // Send request + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending N-EVENT-REPORT Request"); + // Output dataset only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); + } + else + { + DCMNET_INFO("Sending N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &request, reqDataset); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-EVENT-REPORT request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + // Receive response + T_DIMSE_Message response; + cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); + if (cond.bad()) + { + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + + // Check command set + if (response.CommandField == DIMSE_N_EVENT_REPORT_RSP) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received N-EVENT-REPORT Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received N-EVENT-REPORT Response (" + << DU_neventReportStatusString(response.msg.NEventReportRSP.DimseStatus) << ")"); + } + } + else + { + DCMNET_ERROR("Expected N-EVENT-REPORT response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, response.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + // Set return value + T_DIMSE_N_EventReportRSP& eventReportRsp = response.msg.NEventReportRSP; + rspStatusCode = eventReportRsp.DimseStatus; + + // Check whether there is a dataset to be received + if (eventReportRsp.DataSetType == DIMSE_DATASET_PRESENT) + { + // this should never happen + DcmDataset* tempDataset = NULL; + T_ASC_PresentationContextID tempID; + // Receive dataset + cond = receiveDIMSEDataset(&tempID, &tempDataset); + if (cond.good()) + { + DCMNET_WARN("Received unexpected dataset after N-EVENT-REPORT response, ignoring"); + delete tempDataset; + } + else + { + DCMNET_ERROR("Failed receiving unexpected dataset after N-EVENT-REPORT response: " + << DimseCondition::dump(tempStr, cond)); + return DIMSE_BADDATA; + } + } + + // Check whether the message ID being responded to is equal to the message ID of the request + if (eventReportRsp.MessageIDBeingRespondedTo != eventReportReq.MessageID) + { + DCMNET_ERROR("Received response with wrong message ID (" << eventReportRsp.MessageIDBeingRespondedTo + << " instead of " << eventReportReq.MessageID << ")"); + return DIMSE_BADMESSAGE; + } + + return cond; } +Uint16 DcmSCP::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& /*reqMessage*/, DcmDataset* /*reqDataset*/) +{ + // we default to success + return STATUS_Success; +} /* ************************************************************************* */ /* General message handling */ @@ -1412,366 +1496,406 @@ Uint16 DcmSCP::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ & /*reqMessage*/, void DcmSCP::notifySENDProgress(const unsigned long byteCount) { - DCMNET_TRACE("Bytes sent: " << byteCount); + DCMNET_TRACE("Bytes sent: " << byteCount); } - void DcmSCP::notifyRECEIVEProgress(const unsigned long byteCount) { - DCMNET_TRACE("Bytes received: " << byteCount); + DCMNET_TRACE("Bytes received: " << byteCount); } - /* ************************************************************************* */ /* Various helpers */ /* ************************************************************************* */ // Sends a DIMSE command and possibly also instance data to the configured peer DICOM application OFCondition DcmSCP::sendDIMSEMessage(const T_ASC_PresentationContextID presID, - T_DIMSE_Message *message, - DcmDataset *dataObject, - DcmDataset *statusDetail, - DcmDataset **commandSet) -{ - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - if (message == NULL) - return DIMSE_NULLKEY; - - OFCondition cond; - /* call the corresponding DIMSE function to sent the message */ - if (m_cfg->getProgressNotificationMode()) - { - cond = DIMSE_sendMessageUsingMemoryData(m_assoc, presID, message, statusDetail, dataObject, - callbackSENDProgress, this /*callbackData*/, commandSet); - } else { - cond = DIMSE_sendMessageUsingMemoryData(m_assoc, presID, message, statusDetail, dataObject, - NULL /*callback*/, NULL /*callbackData*/, commandSet); - } - return cond; + T_DIMSE_Message* message, + DcmDataset* dataObject, + DcmDataset* statusDetail, + DcmDataset** commandSet) +{ + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + if (message == NULL) + return DIMSE_NULLKEY; + + OFCondition cond; + /* call the corresponding DIMSE function to sent the message */ + if (m_cfg->getProgressNotificationMode()) + { + cond = DIMSE_sendMessageUsingMemoryData(m_assoc, + presID, + message, + statusDetail, + dataObject, + callbackSENDProgress, + this /*callbackData*/, + commandSet); + } + else + { + cond = DIMSE_sendMessageUsingMemoryData( + m_assoc, presID, message, statusDetail, dataObject, NULL /*callback*/, NULL /*callbackData*/, commandSet); + } + return cond; } // ---------------------------------------------------------------------------- // Receive DIMSE command (excluding dataset!) over the currently open association -OFCondition DcmSCP::receiveDIMSECommand(T_ASC_PresentationContextID *presID, - T_DIMSE_Message *message, - DcmDataset **statusDetail, - DcmDataset **commandSet, +OFCondition DcmSCP::receiveDIMSECommand(T_ASC_PresentationContextID* presID, + T_DIMSE_Message* message, + DcmDataset** statusDetail, + DcmDataset** commandSet, const Uint32 timeout) { - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - if (timeout > 0) - { - /* call the corresponding DIMSE function to receive the command (use specified timeout) */ - cond = DIMSE_receiveCommand(m_assoc, DIMSE_NONBLOCKING, timeout, presID, - message, statusDetail, commandSet); - } else { - /* call the corresponding DIMSE function to receive the command (use default timeout) */ - cond = DIMSE_receiveCommand(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), presID, - message, statusDetail, commandSet); - } - return cond; + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + + OFCondition cond; + if (timeout > 0) + { + /* call the corresponding DIMSE function to receive the command (use specified timeout) */ + cond = DIMSE_receiveCommand(m_assoc, DIMSE_NONBLOCKING, timeout, presID, message, statusDetail, commandSet); + } + else + { + /* call the corresponding DIMSE function to receive the command (use default timeout) */ + cond = DIMSE_receiveCommand(m_assoc, + m_cfg->getDIMSEBlockingMode(), + m_cfg->getDIMSETimeout(), + presID, + message, + statusDetail, + commandSet); + } + return cond; } // ---------------------------------------------------------------------------- // Receives one dataset (of instance data) via network from another DICOM application in memory -OFCondition DcmSCP::receiveDIMSEDataset(T_ASC_PresentationContextID *presID, - DcmDataset **dataObject) -{ - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - /* call the corresponding DIMSE function to receive the dataset */ - if (m_cfg->getProgressNotificationMode()) - { - cond = DIMSE_receiveDataSetInMemory(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - presID, dataObject, callbackRECEIVEProgress, this /*callbackData*/); - } else { - cond = DIMSE_receiveDataSetInMemory(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - presID, dataObject, NULL /*callback*/, NULL /*callbackData*/); - } - - if (cond.good()) - { - DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); - } else { - OFString tempStr; - DCMNET_ERROR("Unable to receive dataset on presentation context " - << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); - } - return cond; +OFCondition DcmSCP::receiveDIMSEDataset(T_ASC_PresentationContextID* presID, DcmDataset** dataObject) +{ + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + + OFCondition cond; + /* call the corresponding DIMSE function to receive the dataset */ + if (m_cfg->getProgressNotificationMode()) + { + cond = DIMSE_receiveDataSetInMemory(m_assoc, + m_cfg->getDIMSEBlockingMode(), + m_cfg->getDIMSETimeout(), + presID, + dataObject, + callbackRECEIVEProgress, + this /*callbackData*/); + } + else + { + cond = DIMSE_receiveDataSetInMemory(m_assoc, + m_cfg->getDIMSEBlockingMode(), + m_cfg->getDIMSETimeout(), + presID, + dataObject, + NULL /*callback*/, + NULL /*callbackData*/); + } + + if (cond.good()) + { + DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); + } + else + { + OFString tempStr; + DCMNET_ERROR("Unable to receive dataset on presentation context " + << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); + } + return cond; } // ---------------------------------------------------------------------------- // Receives one C-STORE request dataset via network from another DICOM application // (and store it directly to file) -OFCondition DcmSCP::receiveSTORERequestDataset(T_ASC_PresentationContextID *presID, - T_DIMSE_C_StoreRQ &reqMessage, - const OFString &filename) -{ - if (m_assoc == NULL) - return DIMSE_ILLEGALASSOCIATION; - if (filename.empty()) - return EC_InvalidFilename; - - OFString tempStr; - DcmOutputFileStream *filestream = NULL; - // Receive dataset over the network and write it directly to a file - OFCondition cond = DIMSE_createFilestream(filename, &reqMessage, m_assoc, *presID, - OFTrue /*writeMetaheader*/, &filestream); - if (cond.good()) - { - if (m_cfg->getProgressNotificationMode()) - { - cond = DIMSE_receiveDataSetInFile(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - presID, filestream, callbackRECEIVEProgress, this /*callbackData*/); - } else { - cond = DIMSE_receiveDataSetInFile(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - presID, filestream, NULL /*callback*/, NULL /*callbackData*/); - } - delete filestream; +OFCondition DcmSCP::receiveSTORERequestDataset(T_ASC_PresentationContextID* presID, + T_DIMSE_C_StoreRQ& reqMessage, + const OFString& filename) +{ + if (m_assoc == NULL) + return DIMSE_ILLEGALASSOCIATION; + if (filename.empty()) + return EC_InvalidFilename; + + OFString tempStr; + DcmOutputFileStream* filestream = NULL; + // Receive dataset over the network and write it directly to a file + OFCondition cond + = DIMSE_createFilestream(filename, &reqMessage, m_assoc, *presID, OFTrue /*writeMetaheader*/, &filestream); if (cond.good()) { - DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID) - << " and stored it directly to file"); - } else { - DCMNET_ERROR("Unable to receive dataset on presentation context " - << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); - // Delete created file in case of error - OFStandard::deleteFile(filename); - } - - } else { - - DCMNET_ERROR("Unable to receive dataset on presentation context " - << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); - // Could not create the filestream, so ignore the dataset - DIC_UL bytesRead = 0; - DIC_UL pdvCount = 0; - DCMNET_DEBUG("Ignoring incoming dataset and returning an error status to the SCU"); - cond = DIMSE_ignoreDataSet(m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), - &bytesRead, &pdvCount); - if (cond.good()) + if (m_cfg->getProgressNotificationMode()) + { + cond = DIMSE_receiveDataSetInFile(m_assoc, + m_cfg->getDIMSEBlockingMode(), + m_cfg->getDIMSETimeout(), + presID, + filestream, + callbackRECEIVEProgress, + this /*callbackData*/); + } + else + { + cond = DIMSE_receiveDataSetInFile(m_assoc, + m_cfg->getDIMSEBlockingMode(), + m_cfg->getDIMSETimeout(), + presID, + filestream, + NULL /*callback*/, + NULL /*callbackData*/); + } + delete filestream; + if (cond.good()) + { + DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID) + << " and stored it directly to file"); + } + else + { + DCMNET_ERROR("Unable to receive dataset on presentation context " + << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); + // Delete created file in case of error + OFStandard::deleteFile(filename); + } + } + else { - tempStr = "Cannot create file: " + filename; - cond = makeDcmnetCondition(DIMSEC_OUTOFRESOURCES, OF_error, tempStr.c_str()); + + DCMNET_ERROR("Unable to receive dataset on presentation context " + << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); + // Could not create the filestream, so ignore the dataset + DIC_UL bytesRead = 0; + DIC_UL pdvCount = 0; + DCMNET_DEBUG("Ignoring incoming dataset and returning an error status to the SCU"); + cond = DIMSE_ignoreDataSet( + m_assoc, m_cfg->getDIMSEBlockingMode(), m_cfg->getDIMSETimeout(), &bytesRead, &pdvCount); + if (cond.good()) + { + tempStr = "Cannot create file: " + filename; + cond = makeDcmnetCondition(DIMSEC_OUTOFRESOURCES, OF_error, tempStr.c_str()); + } } - } - return cond; + return cond; } // ---------------------------------------------------------------------------- -OFBool DcmSCP::addStatusDetail(DcmDataset **statusDetail, - const DcmElement *elem) +OFBool DcmSCP::addStatusDetail(DcmDataset** statusDetail, const DcmElement* elem) { - DCMNET_TRACE("Add element to status detail"); - // If no element was passed, return to the caller. - if( elem == NULL ) - return OFFalse; + DCMNET_TRACE("Add element to status detail"); + // If no element was passed, return to the caller. + if (elem == NULL) + return OFFalse; - DcmAttributeTag *at; - DcmLongString *lo; + DcmAttributeTag* at; + DcmLongString* lo; - // Create the container object if necessary - if( *statusDetail == NULL ) - *statusDetail = new DcmDataset(); + // Create the container object if necessary + if (*statusDetail == NULL) + *statusDetail = new DcmDataset(); - if (statusDetail == NULL) - { - DCMNET_ERROR("Cannot create status detail object, memory exhausted!"); - return OFFalse; - } - - // Determine the element's data type - DcmVR vr( elem->ident() ); - - // Depending on the element's identification, insert different - // types of objects into the container. - switch( elem->ident() ) - { - case EVR_LO: - lo = new DcmLongString( *((DcmLongString*)elem) ); - if( lo->getLength() > vr.getMaxValueLength() ) - { - DCMNET_WARN("Value inside given LO attribute too large for status detail (max " << OFstatic_cast(Uint32, vr.getMaxValueLength()) << ") for " << vr.getVRName()); - } - (*statusDetail)->insert( lo, OFTrue /*replaceOld*/ ); - // Print debug information - { - OFOStringStream oss; - lo->print(oss); - OFSTRINGSTREAM_GETSTR(oss, strtemp); - DCMNET_DEBUG("Adding LO status detail information: " << strtemp); - OFSTRINGSTREAM_FREESTR(tmpString) - } - break; - case EVR_AT: - at = new DcmAttributeTag( *((DcmAttributeTag*)elem) ); - if( at->getLength() > vr.getMaxValueLength() ) - { - DCMNET_WARN("Value inside given AT attribute too large for status detail (max " << OFstatic_cast(Uint32, vr.getMaxValueLength()) << ") for " << vr.getVRName()); - } - (*statusDetail)->insert( at, OFTrue /*replaceOld*/ ); - // Print debug information - { - OFOStringStream oss; - at->print(oss); - OFSTRINGSTREAM_GETSTR(oss, strtemp); - DCMNET_DEBUG("Adding AT status detail information: " << strtemp); - OFSTRINGSTREAM_FREESTR(tmpString) - } - break; - default: // other status detail is not supported - DCMNET_ERROR("Cannot add status detail, unsupported detail attribute type: " << vr.getVRName()); - return OFFalse; - break; - } - return OFTrue; + if (statusDetail == NULL) + { + DCMNET_ERROR("Cannot create status detail object, memory exhausted!"); + return OFFalse; + } + + // Determine the element's data type + DcmVR vr(elem->ident()); + + // Depending on the element's identification, insert different + // types of objects into the container. + switch (elem->ident()) + { + case EVR_LO: + lo = new DcmLongString(*((DcmLongString*)elem)); + if (lo->getLength() > vr.getMaxValueLength()) + { + DCMNET_WARN("Value inside given LO attribute too large for status detail (max " + << OFstatic_cast(Uint32, vr.getMaxValueLength()) << ") for " << vr.getVRName()); + } + (*statusDetail)->insert(lo, OFTrue /*replaceOld*/); + // Print debug information + { + OFOStringStream oss; + lo->print(oss); + OFSTRINGSTREAM_GETSTR(oss, strtemp); + DCMNET_DEBUG("Adding LO status detail information: " << strtemp); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + case EVR_AT: + at = new DcmAttributeTag(*((DcmAttributeTag*)elem)); + if (at->getLength() > vr.getMaxValueLength()) + { + DCMNET_WARN("Value inside given AT attribute too large for status detail (max " + << OFstatic_cast(Uint32, vr.getMaxValueLength()) << ") for " << vr.getVRName()); + } + (*statusDetail)->insert(at, OFTrue /*replaceOld*/); + // Print debug information + { + OFOStringStream oss; + at->print(oss); + OFSTRINGSTREAM_GETSTR(oss, strtemp); + DCMNET_DEBUG("Adding AT status detail information: " << strtemp); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + default: // other status detail is not supported + DCMNET_ERROR("Cannot add status detail, unsupported detail attribute type: " << vr.getVRName()); + return OFFalse; + break; + } + return OFTrue; } // ---------------------------------------------------------------------------- void DcmSCP::forceAssociationRefuse(const OFBool doRefuse) { - m_cfg->forceAssociationRefuse(doRefuse); + m_cfg->forceAssociationRefuse(doRefuse); } // ---------------------------------------------------------------------------- void DcmSCP::setMaxReceivePDULength(const Uint32 maxRecPDU) { - m_cfg->setMaxReceivePDULength(maxRecPDU); + m_cfg->setMaxReceivePDULength(maxRecPDU); } // ---------------------------------------------------------------------------- -OFCondition DcmSCP::setEnableVerification(const OFString &profile) +OFCondition DcmSCP::setEnableVerification(const OFString& profile) { - OFList xfers; - xfers.push_back(UID_LittleEndianExplicitTransferSyntax); - xfers.push_back(UID_BigEndianExplicitTransferSyntax); - xfers.push_back(UID_LittleEndianImplicitTransferSyntax); - return m_cfg->addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_DEFAULT, profile); + OFList xfers; + xfers.push_back(UID_LittleEndianExplicitTransferSyntax); + xfers.push_back(UID_BigEndianExplicitTransferSyntax); + xfers.push_back(UID_LittleEndianImplicitTransferSyntax); + return m_cfg->addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_DEFAULT, profile); } // ---------------------------------------------------------------------------- - // ---------------------------------------------------------------------------- -OFCondition DcmSCP::addPresentationContext(const OFString &abstractSyntax, - const OFList &xferSyntaxes, +OFCondition DcmSCP::addPresentationContext(const OFString& abstractSyntax, + const OFList& xferSyntaxes, const T_ASC_SC_ROLE requestorRole, - const OFString &profile) + const OFString& profile) { - return m_cfg->addPresentationContext(abstractSyntax, xferSyntaxes, requestorRole, profile); + return m_cfg->addPresentationContext(abstractSyntax, xferSyntaxes, requestorRole, profile); } // ---------------------------------------------------------------------------- void DcmSCP::setPort(const Uint16 port) { - m_cfg->setPort(port); + m_cfg->setPort(port); } // ---------------------------------------------------------------------------- -void DcmSCP::setAETitle(const OFString &aetitle) +void DcmSCP::setAETitle(const OFString& aetitle) { - m_cfg->setAETitle(aetitle); + m_cfg->setAETitle(aetitle); } // ---------------------------------------------------------------------------- void DcmSCP::setRespondWithCalledAETitle(const OFBool useCalled) { - m_cfg->setRespondWithCalledAETitle(useCalled); + m_cfg->setRespondWithCalledAETitle(useCalled); } // ---------------------------------------------------------------------------- -OFCondition DcmSCP::loadAssociationCfgFile(const OFString &assocFile) +OFCondition DcmSCP::loadAssociationCfgFile(const OFString& assocFile) { - return m_cfg->loadAssociationCfgFile(assocFile); + return m_cfg->loadAssociationCfgFile(assocFile); } // ---------------------------------------------------------------------------- -OFCondition DcmSCP::setAndCheckAssociationProfile(const OFString &profileName) +OFCondition DcmSCP::setAndCheckAssociationProfile(const OFString& profileName) { - return m_cfg->setAndCheckAssociationProfile(profileName); + return m_cfg->setAndCheckAssociationProfile(profileName); } // ---------------------------------------------------------------------------- void DcmSCP::setConnectionBlockingMode(const DUL_BLOCKOPTIONS blockingMode) { - m_cfg->setConnectionBlockingMode(blockingMode); + m_cfg->setConnectionBlockingMode(blockingMode); } // ---------------------------------------------------------------------------- void DcmSCP::setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode) { - m_cfg->setDIMSEBlockingMode(blockingMode); + m_cfg->setDIMSEBlockingMode(blockingMode); } // ---------------------------------------------------------------------------- void DcmSCP::setDIMSETimeout(const Uint32 dimseTimeout) { - m_cfg->setDIMSETimeout(dimseTimeout); + m_cfg->setDIMSETimeout(dimseTimeout); } // ---------------------------------------------------------------------------- void DcmSCP::setACSETimeout(const Uint32 acseTimeout) { - m_cfg->setACSETimeout(acseTimeout); + m_cfg->setACSETimeout(acseTimeout); } // ---------------------------------------------------------------------------- void DcmSCP::setConnectionTimeout(const Uint32 timeout) { - m_cfg->setConnectionTimeout(timeout); + m_cfg->setConnectionTimeout(timeout); } // ---------------------------------------------------------------------------- void DcmSCP::setVerbosePCMode(const OFBool mode) { - m_cfg->setVerbosePCMode(mode); + m_cfg->setVerbosePCMode(mode); } // ---------------------------------------------------------------------------- void DcmSCP::setHostLookupEnabled(const OFBool mode) { - m_cfg->setHostLookupEnabled(mode); + m_cfg->setHostLookupEnabled(mode); } // ---------------------------------------------------------------------------- void DcmSCP::setProgressNotificationMode(const OFBool mode) { - m_cfg->setProgressNotificationMode(mode); + m_cfg->setProgressNotificationMode(mode); } // ---------------------------------------------------------------------------- void DcmSCP::setAlwaysAcceptDefaultRole(const OFBool enabled) { - m_cfg->setAlwaysAcceptDefaultRole(enabled); + m_cfg->setAlwaysAcceptDefaultRole(enabled); } // ---------------------------------------------------------------------------- @@ -1780,134 +1904,134 @@ void DcmSCP::setAlwaysAcceptDefaultRole(const OFBool enabled) OFBool DcmSCP::getRefuseAssociation() const { - return m_cfg->getRefuseAssociation(); + return m_cfg->getRefuseAssociation(); } // ---------------------------------------------------------------------------- Uint32 DcmSCP::getMaxReceivePDULength() const { - return m_cfg->getMaxReceivePDULength(); + return m_cfg->getMaxReceivePDULength(); } // ---------------------------------------------------------------------------- Uint16 DcmSCP::getPort() const { - return m_cfg->getPort(); + return m_cfg->getPort(); } // ---------------------------------------------------------------------------- -const OFString &DcmSCP::getAETitle() const +const OFString& DcmSCP::getAETitle() const { - return m_cfg->getAETitle(); + return m_cfg->getAETitle(); } // ---------------------------------------------------------------------------- OFBool DcmSCP::getRespondWithCalledAETitle() const { - return m_cfg->getRespondWithCalledAETitle(); + return m_cfg->getRespondWithCalledAETitle(); } // ---------------------------------------------------------------------------- DUL_BLOCKOPTIONS DcmSCP::getConnectionBlockingMode() const { - return m_cfg->getConnectionBlockingMode(); + return m_cfg->getConnectionBlockingMode(); } // ---------------------------------------------------------------------------- T_DIMSE_BlockingMode DcmSCP::getDIMSEBlockingMode() const { - return m_cfg->getDIMSEBlockingMode(); + return m_cfg->getDIMSEBlockingMode(); } // ---------------------------------------------------------------------------- Uint32 DcmSCP::getDIMSETimeout() const { - return m_cfg->getDIMSETimeout(); + return m_cfg->getDIMSETimeout(); } // ---------------------------------------------------------------------------- Uint32 DcmSCP::getConnectionTimeout() const { - return m_cfg->getConnectionTimeout(); + return m_cfg->getConnectionTimeout(); } // ---------------------------------------------------------------------------- Uint32 DcmSCP::getACSETimeout() const { - return m_cfg->getACSETimeout(); + return m_cfg->getACSETimeout(); } // ---------------------------------------------------------------------------- OFBool DcmSCP::getVerbosePCMode() const { - return m_cfg->getVerbosePCMode(); + return m_cfg->getVerbosePCMode(); } // ---------------------------------------------------------------------------- OFBool DcmSCP::getHostLookupEnabled() const { - return m_cfg->getHostLookupEnabled(); + return m_cfg->getHostLookupEnabled(); } // ---------------------------------------------------------------------------- OFBool DcmSCP::getProgressNotificationMode() const { - return m_cfg->getProgressNotificationMode(); + return m_cfg->getProgressNotificationMode(); } // ---------------------------------------------------------------------------- OFBool DcmSCP::isConnected() const { - return (m_assoc != NULL) && (m_assoc->DULassociation != NULL); + return (m_assoc != NULL) && (m_assoc->DULassociation != NULL); } // ---------------------------------------------------------------------------- OFString DcmSCP::getPeerAETitle() const { - if (m_assoc == NULL) - return ""; - return m_assoc->params->DULparams.callingAPTitle; + if (m_assoc == NULL) + return ""; + return m_assoc->params->DULparams.callingAPTitle; } // ---------------------------------------------------------------------------- OFString DcmSCP::getCalledAETitle() const { - if (m_assoc == NULL) - return ""; - return m_assoc->params->DULparams.calledAPTitle; + if (m_assoc == NULL) + return ""; + return m_assoc->params->DULparams.calledAPTitle; } // ---------------------------------------------------------------------------- Uint32 DcmSCP::getPeerMaxPDULength() const { - if (m_assoc == NULL) - return 0; - return m_assoc->params->theirMaxPDUReceiveSize; + if (m_assoc == NULL) + return 0; + return m_assoc->params->theirMaxPDUReceiveSize; } // ---------------------------------------------------------------------------- OFString DcmSCP::getPeerIP() const { - if (m_assoc == NULL) - return ""; - return m_assoc->params->DULparams.callingPresentationAddress; + if (m_assoc == NULL) + return ""; + return m_assoc->params->DULparams.callingPresentationAddress; } // ---------------------------------------------------------------------------- @@ -1915,155 +2039,148 @@ OFString DcmSCP::getPeerIP() const void DcmSCP::dropAndDestroyAssociation() { - if (m_assoc) - { - ASC_dropSCPAssociation( m_assoc ); - ASC_destroyAssociation( &m_assoc ); - } + if (m_assoc) + { + ASC_dropSCPAssociation(m_assoc); + ASC_destroyAssociation(&m_assoc); + } } - /* ************************************************************************** */ /* Notify functions */ /* ************************************************************************** */ - -void DcmSCP::notifyAssociationRequest(const T_ASC_Parameters ¶ms, - DcmSCPActionType & /* desiredAction */) +void DcmSCP::notifyAssociationRequest(const T_ASC_Parameters& params, DcmSCPActionType& /* desiredAction */) { - // Dump some information if required - DCMNET_INFO("Association Received " << params.DULparams.callingPresentationAddress << ": " - << params.DULparams.callingAPTitle << " -> " - << params.DULparams.calledAPTitle); + // Dump some information if required + DCMNET_INFO("Association Received " << params.DULparams.callingPresentationAddress << ": " + << params.DULparams.callingAPTitle << " -> " << params.DULparams.calledAPTitle); // Dump more information if required - OFString tempStr; - if (m_cfg->getVerbosePCMode()) - DCMNET_INFO("Incoming Association Request:" << OFendl << ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RQ)); - else - DCMNET_DEBUG("Incoming Association Request:" << OFendl << ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RQ)); + OFString tempStr; + if (m_cfg->getVerbosePCMode()) + DCMNET_INFO("Incoming Association Request:" << OFendl + << ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RQ)); + else + DCMNET_DEBUG("Incoming Association Request:" << OFendl + << ASC_dumpParameters(tempStr, m_assoc->params, ASC_ASSOC_RQ)); } // ---------------------------------------------------------------------------- OFBool DcmSCP::checkCalledAETitleAccepted(const OFString& /*calledAETitle*/) { - return OFTrue; + return OFTrue; } // ---------------------------------------------------------------------------- OFBool DcmSCP::checkCallingAETitleAccepted(const OFString& /*callingAETitle*/) { - return OFTrue; + return OFTrue; } // ---------------------------------------------------------------------------- OFBool DcmSCP::checkCallingHostAccepted(const OFString& /*hostOrIP*/) { - return OFTrue; + return OFTrue; } // ---------------------------------------------------------------------------- void DcmSCP::notifyAssociationAcknowledge() { - DCMNET_DEBUG("DcmSCP: Association Acknowledged"); + DCMNET_DEBUG("DcmSCP: Association Acknowledged"); } // ---------------------------------------------------------------------------- void DcmSCP::notifyReleaseRequest() { - DCMNET_INFO("Received Association Release Request"); + DCMNET_INFO("Received Association Release Request"); } - // ---------------------------------------------------------------------------- void DcmSCP::notifyAbortRequest() { - DCMNET_INFO("Received Association Abort Request"); + DCMNET_INFO("Received Association Abort Request"); } // ---------------------------------------------------------------------------- void DcmSCP::notifyAssociationTermination() { - DCMNET_DEBUG("DcmSCP: Association Terminated"); + DCMNET_DEBUG("DcmSCP: Association Terminated"); } // ---------------------------------------------------------------------------- void DcmSCP::notifyConnectionTimeout() { - DCMNET_TRACE("Connection timeout encountered in non-blocking mode"); + DCMNET_TRACE("Connection timeout encountered in non-blocking mode"); } // ---------------------------------------------------------------------------- -void DcmSCP::notifyDIMSEError(const OFCondition &cond) +void DcmSCP::notifyDIMSEError(const OFCondition& cond) { - OFString tempStr; - DCMNET_DEBUG("DIMSE Error, detail (if available): " << DimseCondition::dump(tempStr, cond)); + OFString tempStr; + DCMNET_DEBUG("DIMSE Error, detail (if available): " << DimseCondition::dump(tempStr, cond)); } // ---------------------------------------------------------------------------- OFBool DcmSCP::stopAfterCurrentAssociation() { - return OFFalse; + return OFFalse; } // ---------------------------------------------------------------------------- OFBool DcmSCP::stopAfterConnectionTimeout() { - return OFFalse; + return OFFalse; } - /* ************************************************************************* */ /* Callback functions */ /* ************************************************************************* */ -void DcmSCP::callbackSENDProgress(void *callbackContext, - const unsigned long byteCount) +void DcmSCP::callbackSENDProgress(void* callbackContext, const unsigned long byteCount) { - if (callbackContext != NULL) - OFreinterpret_cast(DcmSCP *, callbackContext)->notifySENDProgress(byteCount); + if (callbackContext != NULL) + OFreinterpret_cast(DcmSCP*, callbackContext)->notifySENDProgress(byteCount); } - -void DcmSCP::callbackRECEIVEProgress(void *callbackContext, - const unsigned long byteCount) +void DcmSCP::callbackRECEIVEProgress(void* callbackContext, const unsigned long byteCount) { - if (callbackContext != NULL) - OFreinterpret_cast(DcmSCP *, callbackContext)->notifyRECEIVEProgress(byteCount); + if (callbackContext != NULL) + OFreinterpret_cast(DcmSCP*, callbackContext)->notifyRECEIVEProgress(byteCount); } - /* ************************************************************************* */ /* Static helper functions */ /* ************************************************************************* */ -OFBool DcmSCP::getPresentationContextInfo(const T_ASC_Association *assoc, +OFBool DcmSCP::getPresentationContextInfo(const T_ASC_Association* assoc, const Uint8 presID, - DcmPresentationContextInfo &presInfo) -{ - if (assoc != NULL) - { - DUL_PRESENTATIONCONTEXT *pc = findPresentationContextID(assoc->params->DULparams.acceptedPresentationContext, presID); - if (pc != NULL) - { - presInfo.abstractSyntax = pc->abstractSyntax; - presInfo.acceptedTransferSyntax = pc->acceptedTransferSyntax; - presInfo.presentationContextID = pc->presentationContextID; - presInfo.proposedSCRole = pc->proposedSCRole; - presInfo.acceptedSCRole = pc->acceptedSCRole; - return OFTrue; - } - } - return OFFalse; + DcmPresentationContextInfo& presInfo) +{ + if (assoc != NULL) + { + DUL_PRESENTATIONCONTEXT* pc + = findPresentationContextID(assoc->params->DULparams.acceptedPresentationContext, presID); + if (pc != NULL) + { + presInfo.abstractSyntax = pc->abstractSyntax; + presInfo.acceptedTransferSyntax = pc->acceptedTransferSyntax; + presInfo.presentationContextID = pc->presentationContextID; + presInfo.proposedSCRole = pc->proposedSCRole; + presInfo.acceptedSCRole = pc->acceptedSCRole; + return OFTrue; + } + } + return OFFalse; } diff --git a/dcmnet/libsrc/scpcfg.cc b/dcmnet/libsrc/scpcfg.cc index 61e7f7bd..5debde1f 100644 --- a/dcmnet/libsrc/scpcfg.cc +++ b/dcmnet/libsrc/scpcfg.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2012-2017, OFFIS e.V. + * Copyright (C) 2012-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -20,7 +20,6 @@ */ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ - #include "dcmtk/dcmnet/scpcfg.h" #include "dcmtk/dcmnet/diutil.h" @@ -40,7 +39,8 @@ DcmSCPConfig::DcmSCPConfig() : m_verbosePCMode(OFFalse), m_connectionTimeout(1000), m_respondWithCalledAETitle(OFTrue), - m_progressNotificationMode(OFTrue) + m_progressNotificationMode(OFTrue), + m_tLayer(NULL) { } @@ -297,6 +297,27 @@ OFBool DcmSCPConfig::getProgressNotificationMode() const // ---------------------------------------------------------------------------- +OFBool DcmSCPConfig::transportLayerEnabled() const +{ + return (m_tLayer != NULL); +} + +// ---------------------------------------------------------------------------- + +DcmTransportLayer * DcmSCPConfig::getTransportLayer() const +{ + return m_tLayer; +} + +// ---------------------------------------------------------------------------- + +void DcmSCPConfig::setTransportLayer(DcmTransportLayer *tlayer) +{ + m_tLayer = tlayer; +} + +// ---------------------------------------------------------------------------- + // Reads association configuration from config file OFCondition DcmSCPConfig::loadAssociationCfgFile(const OFString &assocFile) { diff --git a/dcmnet/libsrc/scppool.cc b/dcmnet/libsrc/scppool.cc index a20b07c1..50a2951d 100644 --- a/dcmnet/libsrc/scppool.cc +++ b/dcmnet/libsrc/scppool.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2012-2014, OFFIS e.V. + * Copyright (C) 2012-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -28,6 +28,7 @@ #include "dcmtk/dcmnet/scppool.h" #include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmtls/tlslayer.h" // ---------------------------------------------------------------------------- @@ -64,6 +65,15 @@ OFCondition DcmBaseSCPPool::listen() if( cond.bad() ) return cond; + if (m_cfg.transportLayerEnabled()) + { + cond = ASC_setTransportLayer(network, m_cfg.getTransportLayer(), 0 /* Do not take over ownership */); + if (cond.bad()) + { + DCMNET_ERROR("DcmBaseSCPPool: Error setting secured transport layer: " << cond.text()); + } + } + /* As long as all is fine (or we have been to busy handling last connection request) keep listening */ while ( m_runMode == LISTEN && ( cond.good() || (cond == NET_EC_SCPBusy) ) ) { @@ -71,8 +81,10 @@ OFCondition DcmBaseSCPPool::listen() cond = EC_Normal; // Every incoming connection is handled in a new association object T_ASC_Association *assoc = NULL; + OFBool useSecureLayer = m_cfg.transportLayerEnabled(); + // Listen to a socket for timeout seconds for an association request, accepts TCP connection. - cond = ASC_receiveAssociation( network, &assoc, m_cfg.getMaxReceivePDULength(), NULL, NULL, OFFalse, + cond = ASC_receiveAssociation( network, &assoc, m_cfg.getMaxReceivePDULength(), NULL, NULL, useSecureLayer, m_cfg.getConnectionBlockingMode(), OFstatic_cast(int, m_cfg.getConnectionTimeout()) ); /* If we have a connection request, try to find/create a worker to handle it */ diff --git a/dcmnet/libsrc/scu.cc b/dcmnet/libsrc/scu.cc index 153ea3c2..1e4dd631 100644 --- a/dcmnet/libsrc/scu.cc +++ b/dcmnet/libsrc/scu.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2008-2018, OFFIS e.V. + * Copyright (C) 2008-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -19,528 +19,534 @@ * */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/dcmnet/scu.h" -#include "dcmtk/dcmnet/diutil.h" /* for dcmnet logger */ -#include "dcmtk/dcmdata/dcuid.h" /* for dcmFindUIDName() */ #include "dcmtk/dcmdata/dcostrmf.h" /* for class DcmOutputFileStream */ -#include "dcmtk/ofstd/ofmem.h" /* for OFunique_ptr */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmFindUIDName() */ +#include "dcmtk/dcmnet/diutil.h" /* for dcmnet logger */ +#include "dcmtk/dcmnet/scu.h" +#include "dcmtk/ofstd/ofmem.h" /* for OFunique_ptr */ #ifdef WITH_ZLIB -#include /* for zlibVersion() */ +#include /* for zlibVersion() */ #endif - -DcmSCU::DcmSCU() : - m_assoc(NULL), - m_net(NULL), - m_params(NULL), - m_assocConfigFilename(), - m_assocConfigProfile(), - m_presContexts(), - m_assocConfigFile(), - m_openDIMSERequest(NULL), - m_maxReceivePDULength(ASC_DEFAULTMAXPDU), - m_blockMode(DIMSE_BLOCKING), - m_ourAETitle("ANY-SCU"), - m_peer(), - m_peerAETitle("ANY-SCP"), - m_peerPort(104), - m_dimseTimeout(0), - m_acseTimeout(30), - m_storageDir(), - m_storageMode(DCMSCU_STORAGE_DISK), - m_verbosePCMode(OFFalse), - m_datasetConversionMode(OFFalse), - m_progressNotificationMode(OFTrue) -{ - OFStandard::initializeNetwork(); +DcmSCU::DcmSCU() + : m_assoc(NULL) + , m_net(NULL) + , m_params(NULL) + , m_assocConfigFilename() + , m_assocConfigProfile() + , m_presContexts() + , m_assocConfigFile() + , m_openDIMSERequest(NULL) + , m_maxReceivePDULength(ASC_DEFAULTMAXPDU) + , m_blockMode(DIMSE_BLOCKING) + , m_ourAETitle("ANY-SCU") + , m_peer() + , m_peerAETitle("ANY-SCP") + , m_peerPort(104) + , m_dimseTimeout(0) + , m_acseTimeout(30) + , m_storageDir() + , m_storageMode(DCMSCU_STORAGE_DISK) + , m_verbosePCMode(OFFalse) + , m_datasetConversionMode(OFFalse) + , m_progressNotificationMode(OFTrue) +{ + OFStandard::initializeNetwork(); } void DcmSCU::freeNetwork() { - if ((m_assoc != NULL) || (m_net != NULL) || (m_params != NULL)) - DCMNET_DEBUG("Cleaning up internal association and network structures"); - /* destroy association parameters, i.e. free memory of T_ASC_Parameters. - Usually this is done in ASC_destroyAssociation; however, if we already - have association parameters but not yet an association (e.g. after calling - initNetwork() and negotiateAssociation()), the latter approach may fail. - */ - if (m_params) - { - ASC_destroyAssociationParameters(&m_params); - m_params = NULL; - // make sure destroyAssociation does not try to free params a second time - // (happens in case we have already have an association structure) - if (m_assoc) - m_assoc->params = NULL; - } - // destroy the association, i.e. free memory of T_ASC_Association* structure. - ASC_destroyAssociation(&m_assoc); - // drop the network, i.e. free memory of T_ASC_Network* structure. - ASC_dropNetwork(&m_net); - // Cleanup old DIMSE request if any - delete m_openDIMSERequest; - m_openDIMSERequest = NULL; + if ((m_assoc != NULL) || (m_net != NULL) || (m_params != NULL)) + DCMNET_DEBUG("Cleaning up internal association and network structures"); + /* destroy association parameters, i.e. free memory of T_ASC_Parameters. + Usually this is done in ASC_destroyAssociation; however, if we already + have association parameters but not yet an association (e.g. after calling + initNetwork() and negotiateAssociation()), the latter approach may fail. + */ + if (m_params) + { + ASC_destroyAssociationParameters(&m_params); + m_params = NULL; + // make sure destroyAssociation does not try to free params a second time + // (happens in case we have already have an association structure) + if (m_assoc) + m_assoc->params = NULL; + } + // destroy the association, i.e. free memory of T_ASC_Association* structure. + ASC_destroyAssociation(&m_assoc); + // drop the network, i.e. free memory of T_ASC_Network* structure. + ASC_dropNetwork(&m_net); + // Cleanup old DIMSE request if any + delete m_openDIMSERequest; + m_openDIMSERequest = NULL; } - DcmSCU::~DcmSCU() { - // abort association (if any) and destroy dcmnet data structures - if (isConnected()) - { - closeAssociation(DCMSCU_ABORT_ASSOCIATION); // also frees network - } else { - freeNetwork(); - } + // abort association (if any) and destroy dcmnet data structures + if (isConnected()) + { + closeAssociation(DCMSCU_ABORT_ASSOCIATION); // also frees network + } + else + { + freeNetwork(); + } - OFStandard::shutdownNetwork(); + OFStandard::shutdownNetwork(); } - OFCondition DcmSCU::initNetwork() { - /* Return if SCU is already connected */ - if (isConnected()) - return NET_EC_AlreadyConnected; + /* Return if SCU is already connected */ + if (isConnected()) + return NET_EC_AlreadyConnected; - /* Be sure internal network structures are clean (delete old) */ - freeNetwork(); + /* Be sure internal network structures are clean (delete old) */ + freeNetwork(); - OFString tempStr; - /* initialize network, i.e. create an instance of T_ASC_Network*. */ - OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, m_acseTimeout, &m_net); - if (cond.bad()) - { - DimseCondition::dump(tempStr, cond); - DCMNET_ERROR(tempStr); - return cond; - } + OFString tempStr; + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, m_acseTimeout, &m_net); + if (cond.bad()) + { + DimseCondition::dump(tempStr, cond); + DCMNET_ERROR(tempStr); + return cond; + } - /* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */ - cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength); - if (cond.bad()) - { - DCMNET_ERROR(DimseCondition::dump(tempStr, cond)); - return cond; - } + /* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */ + cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength); + if (cond.bad()) + { + DCMNET_ERROR(DimseCondition::dump(tempStr, cond)); + return cond; + } - /* sets this application's title and the called application's title in the params */ - /* structure. The default values are "ANY-SCU" and "ANY-SCP". */ - ASC_setAPTitles(m_params, m_ourAETitle.c_str(), m_peerAETitle.c_str(), NULL); - - /* Figure out the presentation addresses and copy the */ - /* corresponding values into the association parameters.*/ - DIC_NODENAME peerHost; - const OFString localHost = OFStandard::getHostName(); - /* Since the underlying dcmnet structures reserve only 64 bytes for peer - as well as local host name, we check here for buffer overflow. - */ - if ((m_peer.length() + 5 /* max 65535 */) + 1 /* for ":" */ > 63) - { - DCMNET_ERROR("Maximum length of peer host name '" << m_peer << "' is longer than maximum of 57 characters"); - return EC_IllegalCall; // TODO: need to find better error code - } - if (localHost.size() + 1 > 63) - { - DCMNET_ERROR("Maximum length of local host name '" << localHost << "' is longer than maximum of 62 characters"); - return EC_IllegalCall; // TODO: need to find better error code - } - sprintf(peerHost, "%s:%d", m_peer.c_str(), OFstatic_cast(int, m_peerPort)); - ASC_setPresentationAddresses(m_params, localHost.c_str(), peerHost); + /* sets this application's title and the called application's title in the params */ + /* structure. The default values are "ANY-SCU" and "ANY-SCP". */ + ASC_setAPTitles(m_params, m_ourAETitle.c_str(), m_peerAETitle.c_str(), NULL); + + /* Figure out the presentation addresses and copy the */ + /* corresponding values into the association parameters.*/ + DIC_NODENAME peerHost; + const OFString localHost = OFStandard::getHostName(); + /* Since the underlying dcmnet structures reserve only 64 bytes for peer + as well as local host name, we check here for buffer overflow. + */ + if ((m_peer.length() + 5 /* max 65535 */) + 1 /* for ":" */ > 63) + { + DCMNET_ERROR("Maximum length of peer host name '" << m_peer << "' is longer than maximum of 57 characters"); + return EC_IllegalCall; // TODO: need to find better error code + } + if (localHost.size() + 1 > 63) + { + DCMNET_ERROR("Maximum length of local host name '" << localHost << "' is longer than maximum of 62 characters"); + return EC_IllegalCall; // TODO: need to find better error code + } + sprintf(peerHost, "%s:%d", m_peer.c_str(), OFstatic_cast(int, m_peerPort)); + ASC_setPresentationAddresses(m_params, localHost.c_str(), peerHost); - /* Add presentation contexts */ + /* Add presentation contexts */ - // First, import from config file, if specified - OFCondition result; - if (!m_assocConfigFilename.empty()) - { - DcmAssociationConfiguration assocConfig; - result = DcmAssociationConfigurationFile::initialize(assocConfig, m_assocConfigFilename.c_str()); - if (result.bad()) + // First, import from config file, if specified + OFCondition result; + if (!m_assocConfigFilename.empty()) { - DCMNET_WARN("Unable to parse association configuration file " << m_assocConfigFilename - << " (ignored): " << result.text()); - return result; + DcmAssociationConfiguration assocConfig; + result = DcmAssociationConfigurationFile::initialize(assocConfig, m_assocConfigFilename.c_str()); + if (result.bad()) + { + DCMNET_WARN("Unable to parse association configuration file " << m_assocConfigFilename + << " (ignored): " << result.text()); + return result; + } + else + { + /* perform name mangling for config file key */ + OFString profileName; + const unsigned char* c = OFreinterpret_cast(const unsigned char*, m_assocConfigProfile.c_str()); + while (*c) + { + if (!isspace(*c)) + profileName += OFstatic_cast(char, toupper(*c)); + ++c; + } + + result = assocConfig.setAssociationParameters(profileName.c_str(), *m_params); + if (result.bad()) + { + DCMNET_WARN("Unable to apply association configuration file " << m_assocConfigFilename + << " (ignored): " << result.text()); + return result; + } + } + } + + // Adapt presentation context ID to existing presentation contexts. + // It's important that presentation context IDs are numerated 1,3,5,7...! + Uint32 nextFreePresID = 257; + Uint32 numContexts = ASC_countPresentationContexts(m_params); + if (numContexts <= 127) + { + // Need Uint16 to avoid overflow in currPresID (unsigned char) + nextFreePresID = 2 * numContexts + 1; /* add 1 to point to the next free ID*/ + } + // Print warning if number of overall presentation contexts exceeds 128 + if ((numContexts + m_presContexts.size()) > 128) + { + DCMNET_WARN("Number of presentation contexts exceeds 128 (" << numContexts + m_presContexts.size() + << "). Some contexts will not be negotiated"); } else { - /* perform name mangling for config file key */ - OFString profileName; - const unsigned char *c = OFreinterpret_cast(const unsigned char *, m_assocConfigProfile.c_str()); - while (*c) - { - if (! isspace(*c)) profileName += OFstatic_cast(char, toupper(*c)); - ++c; - } - - result = assocConfig.setAssociationParameters(profileName.c_str(), *m_params); - if (result.bad()) - { - DCMNET_WARN("Unable to apply association configuration file " << m_assocConfigFilename - <<" (ignored): " << result.text()); - return result; - } + DCMNET_TRACE("Configured " << numContexts << " presentation contexts from config file"); + if (m_presContexts.size() > 0) + DCMNET_TRACE("Adding another " << m_presContexts.size() << " presentation contexts configured for SCU"); } - } - // Adapt presentation context ID to existing presentation contexts. - // It's important that presentation context IDs are numerated 1,3,5,7...! - Uint32 nextFreePresID = 257; - Uint32 numContexts = ASC_countPresentationContexts(m_params); - if (numContexts <= 127) - { - // Need Uint16 to avoid overflow in currPresID (unsigned char) - nextFreePresID = 2 * numContexts + 1; /* add 1 to point to the next free ID*/ - } - // Print warning if number of overall presentation contexts exceeds 128 - if ((numContexts + m_presContexts.size()) > 128) - { - DCMNET_WARN("Number of presentation contexts exceeds 128 (" << numContexts + m_presContexts.size() - << "). Some contexts will not be negotiated"); - } - else - { - DCMNET_TRACE("Configured " << numContexts << " presentation contexts from config file"); - if (m_presContexts.size() > 0) - DCMNET_TRACE("Adding another " << m_presContexts.size() << " presentation contexts configured for SCU"); - } + // Add presentation contexts not originating from config file + OFListIterator(DcmSCUPresContext) contIt = m_presContexts.begin(); + OFListConstIterator(DcmSCUPresContext) endOfContList = m_presContexts.end(); + while ((contIt != endOfContList) && (nextFreePresID <= 255)) + { + const Uint16 numTransferSyntaxes = OFstatic_cast(Uint16, (*contIt).transferSyntaxes.size()); + const char** transferSyntaxes = new const char*[numTransferSyntaxes]; + + // Iterate over transfer syntaxes within one presentation context + OFListIterator(OFString) syntaxIt = (*contIt).transferSyntaxes.begin(); + OFListIterator(OFString) endOfSyntaxList = (*contIt).transferSyntaxes.end(); + Uint16 sNum = 0; + // copy all transfer syntaxes to array + while (syntaxIt != endOfSyntaxList) + { + transferSyntaxes[sNum] = (*syntaxIt).c_str(); + ++syntaxIt; + ++sNum; + } - // Add presentation contexts not originating from config file - OFListIterator(DcmSCUPresContext) contIt = m_presContexts.begin(); - OFListConstIterator(DcmSCUPresContext) endOfContList = m_presContexts.end(); - while ((contIt != endOfContList) && (nextFreePresID <= 255)) - { - const Uint16 numTransferSyntaxes = OFstatic_cast(Uint16, (*contIt).transferSyntaxes.size()); - const char** transferSyntaxes = new const char*[numTransferSyntaxes]; - - // Iterate over transfer syntaxes within one presentation context - OFListIterator(OFString) syntaxIt = (*contIt).transferSyntaxes.begin(); - OFListIterator(OFString) endOfSyntaxList = (*contIt).transferSyntaxes.end(); - Uint16 sNum = 0; - // copy all transfer syntaxes to array - while (syntaxIt != endOfSyntaxList) - { - transferSyntaxes[sNum] = (*syntaxIt).c_str(); - ++syntaxIt; - ++sNum; - } - - // add the presentation context - cond = ASC_addPresentationContext(m_params, OFstatic_cast(Uint8, nextFreePresID), - (*contIt).abstractSyntaxName.c_str(), transferSyntaxes, numTransferSyntaxes,(*contIt).roleSelect); - // if adding was successful, prepare presentation context ID for next addition - delete[] transferSyntaxes; - transferSyntaxes = NULL; - if (cond.bad()) - return cond; - contIt++; - // goto next free number, only odd presentation context IDs permitted - nextFreePresID += 2; - } + // add the presentation context + cond = ASC_addPresentationContext(m_params, + OFstatic_cast(Uint8, nextFreePresID), + (*contIt).abstractSyntaxName.c_str(), + transferSyntaxes, + numTransferSyntaxes, + (*contIt).roleSelect); + // if adding was successful, prepare presentation context ID for next addition + delete[] transferSyntaxes; + transferSyntaxes = NULL; + if (cond.bad()) + return cond; + contIt++; + // goto next free number, only odd presentation context IDs permitted + nextFreePresID += 2; + } - numContexts = ASC_countPresentationContexts(m_params); - if (numContexts == 0) - { - DCMNET_ERROR("Cannot initialize network: No presentation contexts defined"); - return NET_EC_NoPresentationContextsDefined; - } - DCMNET_DEBUG("Configured a total of " << numContexts << " presentation contexts for SCU"); + numContexts = ASC_countPresentationContexts(m_params); + if (numContexts == 0) + { + DCMNET_ERROR("Cannot initialize network: No presentation contexts defined"); + return NET_EC_NoPresentationContextsDefined; + } + DCMNET_DEBUG("Configured a total of " << numContexts << " presentation contexts for SCU"); - return cond; + return cond; } - OFCondition DcmSCU::negotiateAssociation() { - /* Return error if SCU is already connected */ - if (isConnected()) - return NET_EC_AlreadyConnected; - - /* dump presentation contexts if required */ - OFString tempStr; - if (m_verbosePCMode) - DCMNET_INFO("Request Parameters:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_RQ)); - else - DCMNET_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_RQ)); - - /* create association, i.e. try to establish a network connection to another */ - /* DICOM application. This call creates an instance of T_ASC_Association*. */ - DCMNET_INFO("Requesting Association"); - OFCondition cond = ASC_requestAssociation(m_net, m_params, &m_assoc); - if (cond.bad()) - { - if (cond == DUL_ASSOCIATIONREJECTED) - { - T_ASC_RejectParameters rej; - ASC_getRejectParameters(m_params, &rej); - DCMNET_DEBUG("Association Rejected:" << OFendl << ASC_printRejectParameters(tempStr, &rej)); - return cond; - } + /* Return error if SCU is already connected */ + if (isConnected()) + return NET_EC_AlreadyConnected; + + /* dump presentation contexts if required */ + OFString tempStr; + if (m_verbosePCMode) + DCMNET_INFO("Request Parameters:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_RQ)); else + DCMNET_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_RQ)); + + /* create association, i.e. try to establish a network connection to another */ + /* DICOM application. This call creates an instance of T_ASC_Association*. */ + DCMNET_INFO("Requesting Association"); + OFCondition cond = ASC_requestAssociation(m_net, m_params, &m_assoc); + if (cond.bad()) { - DCMNET_DEBUG("Association Request Failed: " << DimseCondition::dump(tempStr, cond)); - return cond; + if (cond == DUL_ASSOCIATIONREJECTED) + { + T_ASC_RejectParameters rej; + ASC_getRejectParameters(m_params, &rej); + DCMNET_DEBUG("Association Rejected:" << OFendl << ASC_printRejectParameters(tempStr, &rej)); + return cond; + } + else + { + DCMNET_DEBUG("Association Request Failed: " << DimseCondition::dump(tempStr, cond)); + return cond; + } } - } - /* dump the presentation contexts which have been accepted/refused */ - if (m_verbosePCMode) - DCMNET_INFO("Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_AC)); - else - DCMNET_DEBUG("Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_AC)); + /* dump the presentation contexts which have been accepted/refused */ + if (m_verbosePCMode) + DCMNET_INFO("Association Parameters Negotiated:" << OFendl + << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_AC)); + else + DCMNET_DEBUG("Association Parameters Negotiated:" << OFendl + << ASC_dumpParameters(tempStr, m_params, ASC_ASSOC_AC)); - /* count the presentation contexts which have been accepted by the SCP */ - /* If there are none, finish the execution */ - if (ASC_countAcceptedPresentationContexts(m_params) == 0) - { - DCMNET_ERROR("No Acceptable Presentation Contexts"); - return NET_EC_NoAcceptablePresentationContexts; - } + /* count the presentation contexts which have been accepted by the SCP */ + /* If there are none, finish the execution */ + if (ASC_countAcceptedPresentationContexts(m_params) == 0) + { + DCMNET_ERROR("No Acceptable Presentation Contexts"); + return NET_EC_NoAcceptablePresentationContexts; + } - /* dump general information concerning the establishment of the network connection if required */ - DCMNET_INFO("Association Accepted (Max Send PDV: " << OFstatic_cast(unsigned long, m_assoc->sendPDVLength) << ")"); - return EC_Normal; + /* dump general information concerning the establishment of the network connection if required */ + DCMNET_INFO("Association Accepted (Max Send PDV: " << OFstatic_cast(unsigned long, m_assoc->sendPDVLength) << ")"); + return EC_Normal; } - -OFCondition DcmSCU::addPresentationContext(const OFString &abstractSyntax, - const OFList &xferSyntaxes, +OFCondition DcmSCU::addPresentationContext(const OFString& abstractSyntax, + const OFList& xferSyntaxes, const T_ASC_SC_ROLE role) { - DcmSCUPresContext presContext; - presContext.abstractSyntaxName = abstractSyntax; - OFListConstIterator(OFString) it = xferSyntaxes.begin(); - OFListConstIterator(OFString) endOfList = xferSyntaxes.end(); - while (it != endOfList) - { - presContext.transferSyntaxes.push_back(*it); - it++; - } - presContext.roleSelect = role; - m_presContexts.push_back(presContext); - return EC_Normal; + DcmSCUPresContext presContext; + presContext.abstractSyntaxName = abstractSyntax; + OFListConstIterator(OFString) it = xferSyntaxes.begin(); + OFListConstIterator(OFString) endOfList = xferSyntaxes.end(); + while (it != endOfList) + { + presContext.transferSyntaxes.push_back(*it); + it++; + } + presContext.roleSelect = role; + m_presContexts.push_back(presContext); + return EC_Normal; } - -OFCondition DcmSCU::useSecureConnection(DcmTransportLayer *tlayer) +OFCondition DcmSCU::useSecureConnection(DcmTransportLayer* tlayer) { - OFCondition cond = ASC_setTransportLayer(m_net, tlayer, OFFalse /* do not take over ownership */); - if (cond.good()) - cond = ASC_setTransportLayerType(m_params, OFTrue /* use TLS */); - return cond; + OFCondition cond = ASC_setTransportLayer(m_net, tlayer, OFFalse /* do not take over ownership */); + if (cond.good()) + cond = ASC_setTransportLayerType(m_params, OFTrue /* use TLS */); + return cond; } - void DcmSCU::clearPresentationContexts() { - m_presContexts.clear(); - m_assocConfigFilename.clear(); - m_assocConfigProfile.clear(); + m_presContexts.clear(); + m_assocConfigFilename.clear(); + m_assocConfigProfile.clear(); } - // Returns usable presentation context ID for a given abstract syntax UID and // transfer syntax UID. 0 if none matches. -T_ASC_PresentationContextID DcmSCU::findPresentationContextID(const OFString &abstractSyntax, - const OFString &transferSyntax, +T_ASC_PresentationContextID DcmSCU::findPresentationContextID(const OFString& abstractSyntax, + const OFString& transferSyntax, const T_ASC_SC_ROLE requestorRole) { - if (!isConnected()) - return 0; + if (!isConnected()) + return 0; - DUL_PRESENTATIONCONTEXT *pc; - LST_HEAD **l; - OFBool found = OFFalse; + DUL_PRESENTATIONCONTEXT* pc; + LST_HEAD** l; + OFBool found = OFFalse; - if (abstractSyntax.empty()) return 0; + if (abstractSyntax.empty()) + return 0; - /* first of all we look for a presentation context - * matching both abstract and transfer syntax - */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc && !found) - { - found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0); - found &= (pc->result == ASC_P_ACCEPTANCE); - if (!transferSyntax.empty()) // ignore transfer syntax if not specified - found &= (strcmp(pc->acceptedTransferSyntax, transferSyntax.c_str()) == 0); - if (found) found &= pc->acceptedSCRole == ascRole2dulRole(requestorRole); - if (!found) pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } - if (found) - return pc->presentationContextID; + /* first of all we look for a presentation context + * matching both abstract and transfer syntax + */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc && !found) + { + found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0); + found &= (pc->result == ASC_P_ACCEPTANCE); + if (!transferSyntax.empty()) // ignore transfer syntax if not specified + found &= (strcmp(pc->acceptedTransferSyntax, transferSyntax.c_str()) == 0); + if (found) + found &= pc->acceptedSCRole == ascRole2dulRole(requestorRole); + if (!found) + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } + if (found) + return pc->presentationContextID; - return 0; /* not found */ + return 0; /* not found */ } // Returns the presentation context ID that best matches the given abstract syntax UID and // transfer syntax UID. -T_ASC_PresentationContextID DcmSCU::findAnyPresentationContextID(const OFString &abstractSyntax, - const OFString &transferSyntax) -{ - if (m_assoc == NULL) - return 0; - - DUL_PRESENTATIONCONTEXT *pc; - LST_HEAD **l; - OFBool found = OFFalse; - - if (abstractSyntax.empty()) return 0; - - /* first of all we look for a presentation context - * matching both abstract and transfer syntax - */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc && !found) - { - found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0); - found &= (pc->result == ASC_P_ACCEPTANCE); - if (!transferSyntax.empty()) // ignore transfer syntax if not specified - found &= (strcmp(pc->acceptedTransferSyntax, transferSyntax.c_str()) == 0); - if (!found) pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } - if (found) return pc->presentationContextID; - - /* now we look for an explicit VR uncompressed PC. */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc && !found) - { - found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0) - && (pc->result == ASC_P_ACCEPTANCE) - && ((strcmp(pc->acceptedTransferSyntax, UID_LittleEndianExplicitTransferSyntax) == 0) - || (strcmp(pc->acceptedTransferSyntax, UID_BigEndianExplicitTransferSyntax) == 0)); - if (!found) pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } - if (found) return pc->presentationContextID; - - /* now we look for an implicit VR uncompressed PC. */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc && !found) - { - found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0) - && (pc->result == ASC_P_ACCEPTANCE) - && (strcmp(pc->acceptedTransferSyntax, UID_LittleEndianImplicitTransferSyntax) == 0); - if (!found) pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } - if (found) return pc->presentationContextID; +T_ASC_PresentationContextID DcmSCU::findAnyPresentationContextID(const OFString& abstractSyntax, + const OFString& transferSyntax) +{ + if (m_assoc == NULL) + return 0; + + DUL_PRESENTATIONCONTEXT* pc; + LST_HEAD** l; + OFBool found = OFFalse; + + if (abstractSyntax.empty()) + return 0; + + /* first of all we look for a presentation context + * matching both abstract and transfer syntax + */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc && !found) + { + found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0); + found &= (pc->result == ASC_P_ACCEPTANCE); + if (!transferSyntax.empty()) // ignore transfer syntax if not specified + found &= (strcmp(pc->acceptedTransferSyntax, transferSyntax.c_str()) == 0); + if (!found) + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } + if (found) + return pc->presentationContextID; + + /* now we look for an explicit VR uncompressed PC. */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc && !found) + { + found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0) && (pc->result == ASC_P_ACCEPTANCE) + && ((strcmp(pc->acceptedTransferSyntax, UID_LittleEndianExplicitTransferSyntax) == 0) + || (strcmp(pc->acceptedTransferSyntax, UID_BigEndianExplicitTransferSyntax) == 0)); + if (!found) + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } + if (found) + return pc->presentationContextID; + + /* now we look for an implicit VR uncompressed PC. */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc && !found) + { + found = (strcmp(pc->abstractSyntax, abstractSyntax.c_str()) == 0) && (pc->result == ASC_P_ACCEPTANCE) + && (strcmp(pc->acceptedTransferSyntax, UID_LittleEndianImplicitTransferSyntax) == 0); + if (!found) + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); + } + if (found) + return pc->presentationContextID; - /* finally we accept everything we get. - returns 0 if abstract syntax is not supported - */ - return ASC_findAcceptedPresentationContextID(m_assoc, abstractSyntax.c_str()); + /* finally we accept everything we get. + returns 0 if abstract syntax is not supported + */ + return ASC_findAcceptedPresentationContextID(m_assoc, abstractSyntax.c_str()); } void DcmSCU::findPresentationContext(const T_ASC_PresentationContextID presID, - OFString &abstractSyntax, - OFString &transferSyntax) -{ - transferSyntax.clear(); - abstractSyntax.clear(); - if (m_assoc == NULL) - return; - - DUL_PRESENTATIONCONTEXT *pc; - LST_HEAD **l; - - /* we look for a presentation context matching - * both abstract and transfer syntax - */ - l = &m_assoc->params->DULparams.acceptedPresentationContext; - pc = (DUL_PRESENTATIONCONTEXT*) LST_Head(l); - (void)LST_Position(l, (LST_NODE*)pc); - while (pc) - { - if (presID == pc->presentationContextID) + OFString& abstractSyntax, + OFString& transferSyntax) +{ + transferSyntax.clear(); + abstractSyntax.clear(); + if (m_assoc == NULL) + return; + + DUL_PRESENTATIONCONTEXT* pc; + LST_HEAD** l; + + /* we look for a presentation context matching + * both abstract and transfer syntax + */ + l = &m_assoc->params->DULparams.acceptedPresentationContext; + pc = (DUL_PRESENTATIONCONTEXT*)LST_Head(l); + (void)LST_Position(l, (LST_NODE*)pc); + while (pc) { - if (pc->result == ASC_P_ACCEPTANCE) - { - // found a match - transferSyntax = pc->acceptedTransferSyntax; - abstractSyntax = pc->abstractSyntax; - } - break; + if (presID == pc->presentationContextID) + { + if (pc->result == ASC_P_ACCEPTANCE) + { + // found a match + transferSyntax = pc->acceptedTransferSyntax; + abstractSyntax = pc->abstractSyntax; + } + break; + } + pc = (DUL_PRESENTATIONCONTEXT*)LST_Next(l); } - pc = (DUL_PRESENTATIONCONTEXT*) LST_Next(l); - } } - Uint16 DcmSCU::nextMessageID() { - if (!isConnected()) - return 0; - else - return m_assoc->nextMsgID++; + if (!isConnected()) + return 0; + else + return m_assoc->nextMsgID++; } - void DcmSCU::closeAssociation(const DcmCloseAssociationType closeType) { - if (!isConnected()) - { - DCMNET_WARN("Closing of association requested but no association active (ignored)"); - return; - } + if (!isConnected()) + { + DCMNET_WARN("Closing of association requested but no association active (ignored)"); + return; + } - OFCondition cond; - OFString tempStr; + OFCondition cond; + OFString tempStr; - /* tear down association, i.e. terminate network connection to SCP */ - switch (closeType) - { - case DCMSCU_RELEASE_ASSOCIATION: - /* release association */ - DCMNET_INFO("Releasing Association"); - cond = ASC_releaseAssociation(m_assoc); - if (cond.bad()) - { - DCMNET_ERROR("Association Release Failed: " << DimseCondition::dump(tempStr, cond)); - return; // TODO: do we really need this? - } - break; - case DCMSCU_ABORT_ASSOCIATION: - /* abort association */ - DCMNET_INFO("Aborting Association"); - cond = ASC_abortAssociation(m_assoc); - if (cond.bad()) - { - DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); - } - break; - case DCMSCU_PEER_REQUESTED_RELEASE: - /* peer requested release */ - DCMNET_ERROR("Protocol Error: Peer requested release (Aborting)"); - DCMNET_INFO("Aborting Association"); - cond = ASC_abortAssociation(m_assoc); - if (cond.bad()) - { - DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); - } - break; - case DCMSCU_PEER_ABORTED_ASSOCIATION: - /* peer aborted association */ - DCMNET_INFO("Peer Aborted Association"); - break; - } + /* tear down association, i.e. terminate network connection to SCP */ + switch (closeType) + { + case DCMSCU_RELEASE_ASSOCIATION: + /* release association */ + DCMNET_INFO("Releasing Association"); + cond = ASC_releaseAssociation(m_assoc); + if (cond.bad()) + { + DCMNET_ERROR("Association Release Failed: " << DimseCondition::dump(tempStr, cond)); + return; // TODO: do we really need this? + } + break; + case DCMSCU_ABORT_ASSOCIATION: + /* abort association */ + DCMNET_INFO("Aborting Association"); + cond = ASC_abortAssociation(m_assoc); + if (cond.bad()) + { + DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); + } + break; + case DCMSCU_PEER_REQUESTED_RELEASE: + /* peer requested release */ + DCMNET_ERROR("Protocol Error: Peer requested release (Aborting)"); + DCMNET_INFO("Aborting Association"); + cond = ASC_abortAssociation(m_assoc); + if (cond.bad()) + { + DCMNET_ERROR("Association Abort Failed: " << DimseCondition::dump(tempStr, cond)); + } + break; + case DCMSCU_PEER_ABORTED_ASSOCIATION: + /* peer aborted association */ + DCMNET_INFO("Peer Aborted Association"); + break; + } - // destroy and free memory of internal association and network structures - freeNetwork(); + // destroy and free memory of internal association and network structures + freeNetwork(); } - OFCondition DcmSCU::releaseAssociation() { OFCondition status = DIMSE_ILLEGALASSOCIATION; @@ -553,7 +559,6 @@ OFCondition DcmSCU::releaseAssociation() return status; } - OFCondition DcmSCU::abortAssociation() { OFCondition status = DIMSE_ILLEGALASSOCIATION; @@ -566,7 +571,6 @@ OFCondition DcmSCU::abortAssociation() return status; } - /* ************************************************************************* */ /* C-ECHO functionality */ /* ************************************************************************* */ @@ -574,92 +578,99 @@ OFCondition DcmSCU::abortAssociation() // Sends C-ECHO request to another DICOM application OFCondition DcmSCU::sendECHORequest(const T_ASC_PresentationContextID presID) { - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - OFCondition cond; - T_ASC_PresentationContextID pcid = presID; + OFCondition cond; + T_ASC_PresentationContextID pcid = presID; - /* If necessary, find appropriate presentation context */ - if (pcid == 0) - pcid = findPresentationContextID(UID_VerificationSOPClass, UID_LittleEndianExplicitTransferSyntax); - if (pcid == 0) - pcid = findPresentationContextID(UID_VerificationSOPClass, UID_BigEndianExplicitTransferSyntax); - if (pcid == 0) - pcid = findPresentationContextID(UID_VerificationSOPClass, UID_LittleEndianImplicitTransferSyntax); - if (pcid == 0) - { - DCMNET_ERROR("No valid presentation context found for sending C-ECHO using SOP Class: " << dcmFindNameOfUID(UID_VerificationSOPClass, "")) ; - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - } + /* If necessary, find appropriate presentation context */ + if (pcid == 0) + pcid = findPresentationContextID(UID_VerificationSOPClass, UID_LittleEndianExplicitTransferSyntax); + if (pcid == 0) + pcid = findPresentationContextID(UID_VerificationSOPClass, UID_BigEndianExplicitTransferSyntax); + if (pcid == 0) + pcid = findPresentationContextID(UID_VerificationSOPClass, UID_LittleEndianImplicitTransferSyntax); + if (pcid == 0) + { + DCMNET_ERROR("No valid presentation context found for sending C-ECHO using SOP Class: " + << dcmFindNameOfUID(UID_VerificationSOPClass, "")); + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + } - /* Now, assemble DIMSE message */ - T_DIMSE_Message msg; - // Make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - T_DIMSE_C_EchoRQ* req = &(msg.msg.CEchoRQ); - // Set type of message - msg.CommandField = DIMSE_C_ECHO_RQ; - // Set message ID - req->MessageID = nextMessageID(); - // Announce no dataset - req->DataSetType = DIMSE_DATASET_NULL; - // Set affected SOP Class UID (always Verification SOP Class) - OFStandard::strlcpy(req->AffectedSOPClassUID, UID_VerificationSOPClass, sizeof(req->AffectedSOPClassUID)); - - /* Send request */ - OFString tempStr; - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-ECHO Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending C-ECHO Request (MsgID " << req->MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, NULL /*dataObject*/); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-ECHO request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + /* Now, assemble DIMSE message */ + T_DIMSE_Message msg; + // Make sure everything is zeroed (especially options) + bzero((char*)&msg, sizeof(msg)); + T_DIMSE_C_EchoRQ* req = &(msg.msg.CEchoRQ); + // Set type of message + msg.CommandField = DIMSE_C_ECHO_RQ; + // Set message ID + req->MessageID = nextMessageID(); + // Announce no dataset + req->DataSetType = DIMSE_DATASET_NULL; + // Set affected SOP Class UID (always Verification SOP Class) + OFStandard::strlcpy(req->AffectedSOPClassUID, UID_VerificationSOPClass, sizeof(req->AffectedSOPClassUID)); + + /* Send request */ + OFString tempStr; + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-ECHO Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); + } + else + { + DCMNET_INFO("Sending C-ECHO Request (MsgID " << req->MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &msg, NULL /*dataObject*/); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-ECHO request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - /* Receive response */ - T_DIMSE_Message rsp; - // Make sure everything is zeroed (especially options) - bzero((char*)&rsp, sizeof(rsp)); + /* Receive response */ + T_DIMSE_Message rsp; + // Make sure everything is zeroed (especially options) + bzero((char*)&rsp, sizeof(rsp)); - DcmDataset* statusDetail = NULL; - cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); - if (cond.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; - } - /* Check whether we received C-ECHO response, otherwise print error */ - if (rsp.CommandField == DIMSE_C_ECHO_RSP) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DcmDataset* statusDetail = NULL; + cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); + if (cond.bad()) { - DCMNET_INFO("Received C-ECHO Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-ECHO Response (" << DU_cechoStatusString(rsp.msg.CEchoRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected C-ECHO response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, rsp.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - /* Print status detail if it was received */ - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } - return EC_Normal; + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + /* Check whether we received C-ECHO response, otherwise print error */ + if (rsp.CommandField == DIMSE_C_ECHO_RSP) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-ECHO Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-ECHO Response (" << DU_cechoStatusString(rsp.msg.CEchoRSP.DimseStatus) << ")"); + } + } + else + { + DCMNET_ERROR("Expected C-ECHO response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, rsp.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + /* Print status detail if it was received */ + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + return EC_Normal; } /* ************************************************************************* */ @@ -668,1022 +679,931 @@ OFCondition DcmSCU::sendECHORequest(const T_ASC_PresentationContextID presID) // Sends C-STORE request to another DICOM application OFCondition DcmSCU::sendSTORERequest(const T_ASC_PresentationContextID presID, - const OFFilename &dicomFile, - DcmDataset *dataset, - Uint16 &rspStatusCode, - const OFString &moveOriginatorAETitle, + const OFFilename& dicomFile, + DcmDataset* dataset, + Uint16& rspStatusCode, + const OFString& moveOriginatorAETitle, const Uint16 moveOriginatorMsgID) { - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - DcmDataset* statusDetail = NULL; - T_DIMSE_Message msg; - // Make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - T_DIMSE_C_StoreRQ* req = &(msg.msg.CStoreRQ); - - // Set type of message - msg.CommandField = DIMSE_C_STORE_RQ; - /* Set message ID */ - req->MessageID = nextMessageID(); - /* Load file if necessary */ - DcmFileFormat *fileformat = NULL; - if (!dicomFile.isEmpty()) - { - fileformat = new DcmFileFormat(); - if (fileformat == NULL) - return EC_MemoryExhausted; - cond = fileformat->loadFile(dicomFile); - if (cond.bad()) - { - delete fileformat; - return cond; - } - dataset = fileformat->getDataset(); - } + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - /* Fill message according to dataset to be sent */ - OFString sopClassUID; - OFString sopInstanceUID; - E_TransferSyntax xferSyntax = EXS_Unknown; - cond = getDatasetInfo(dataset, sopClassUID, sopInstanceUID, xferSyntax); - DcmXfer xfer(xferSyntax); - /* Check whether the information is sufficient */ - if (sopClassUID.empty() || sopInstanceUID.empty() || ((pcid == 0) && (xferSyntax == EXS_Unknown))) - { - DCMNET_ERROR("Cannot send SOP instance, missing information:"); + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + DcmDataset* statusDetail = NULL; + T_DIMSE_Message msg; + // Make sure everything is zeroed (especially options) + bzero((char*)&msg, sizeof(msg)); + T_DIMSE_C_StoreRQ* req = &(msg.msg.CStoreRQ); + + // Set type of message + msg.CommandField = DIMSE_C_STORE_RQ; + /* Set message ID */ + req->MessageID = nextMessageID(); + /* Load file if necessary */ + DcmFileFormat* fileformat = NULL; if (!dicomFile.isEmpty()) - DCMNET_ERROR(" DICOM Filename : " << dicomFile); - DCMNET_ERROR(" SOP Class UID : " << sopClassUID); - DCMNET_ERROR(" SOP Instance UID : " << sopInstanceUID); - DCMNET_ERROR(" Transfer Syntax : " << xfer.getXferName()); - if (pcid == 0) - DCMNET_ERROR(" Pres. Context ID : 0 (find via SOP Class and Transfer Syntax)"); - else - DCMNET_ERROR(" Pres. Context ID : " << OFstatic_cast(unsigned int, pcid)); - delete fileformat; - return cond; - } - OFStandard::strlcpy(req->AffectedSOPClassUID, sopClassUID.c_str(), sizeof(req->AffectedSOPClassUID)); - OFStandard::strlcpy(req->AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(req->AffectedSOPInstanceUID)); - req->DataSetType = DIMSE_DATASET_PRESENT; - req->Priority = DIMSE_PRIORITY_MEDIUM; - - /* If desired (optional), insert MOVE originator information if this C-STORE - was initiated through a C-MOVE request. - */ - if (!moveOriginatorAETitle.empty()) - { - OFStandard::strlcpy(req->MoveOriginatorApplicationEntityTitle, moveOriginatorAETitle.c_str(), sizeof(req->MoveOriginatorApplicationEntityTitle)); - req->opts |= O_STORE_MOVEORIGINATORAETITLE; - } - if (moveOriginatorMsgID != 0) - { - req->MoveOriginatorID = moveOriginatorMsgID; - req->opts |= O_STORE_MOVEORIGINATORID; - } - - /* If no presentation context is specified by the caller ... */ - if (pcid == 0) - { - /* ... try to find an appropriate presentation context automatically */ - pcid = findPresentationContextID(sopClassUID, xfer.getXferID()); - } - else if (m_datasetConversionMode) - { - /* Convert dataset to network transfer syntax (if required) */ - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - /* Check whether given presentation context was accepted by the peer */ - if (abstractSyntax.empty() || transferSyntax.empty()) { - /* Mark presentation context as invalid */ - pcid = 0; - } else { - if (abstractSyntax != sopClassUID) - { - DCMNET_WARN("Inappropriate presentation context with ID " << OFstatic_cast(unsigned int, pcid) - << ": abstract syntax does not match SOP class UID"); - } - /* Try to convert to the negotiated transfer syntax */ - DcmXfer netXfer = DcmXfer(transferSyntax.c_str()).getXfer(); - if (netXfer.getXfer() != xferSyntax) - { - DCMNET_INFO("Converting transfer syntax: " << xfer.getXferName() << " -> " - << netXfer.getXferName()); - cond = dataset->chooseRepresentation(netXfer.getXfer(), NULL); + fileformat = new DcmFileFormat(); + if (fileformat == NULL) + return EC_MemoryExhausted; + cond = fileformat->loadFile(dicomFile); if (cond.bad()) { - DCMNET_ERROR("No conversion to transfer syntax " << netXfer.getXferName() << " possible!"); - delete fileformat; - return cond; + delete fileformat; + return cond; } - } + dataset = fileformat->getDataset(); } - } - /* No appropriate presentation context for sending */ - if (pcid == 0) - { - OFString sopClassName = dcmFindNameOfUID(sopClassUID.c_str(), sopClassUID.c_str()); - OFString xferName = xfer.getXferName(); - DCMNET_ERROR("No presentation context found for sending C-STORE with SOP Class / Transfer Syntax: " - << sopClassName << " / " << xferName); - delete fileformat; - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - } - - /* Send request */ - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-STORE Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending C-STORE Request (MsgID " << req->MessageID << ", " - << dcmSOPClassUIDToModality(sopClassUID.c_str(), "OT") << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, dataset); - delete fileformat; - fileformat = NULL; - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-STORE request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } - - /* Receive response */ - T_DIMSE_Message rsp; - // Make sure everything is zeroed (especially options) - bzero((char*)&rsp, sizeof(rsp)); - cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); - if (cond.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; - } - if (rsp.CommandField == DIMSE_C_STORE_RSP) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + /* Fill message according to dataset to be sent */ + OFString sopClassUID; + OFString sopInstanceUID; + E_TransferSyntax xferSyntax = EXS_Unknown; + cond = getDatasetInfo(dataset, sopClassUID, sopInstanceUID, xferSyntax); + DcmXfer xfer(xferSyntax); + /* Check whether the information is sufficient */ + if (sopClassUID.empty() || sopInstanceUID.empty() || ((pcid == 0) && (xferSyntax == EXS_Unknown))) { - DCMNET_INFO("Received C-STORE Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-STORE Response (" << DU_cstoreStatusString(rsp.msg.CStoreRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected C-STORE response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, rsp.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - T_DIMSE_C_StoreRSP storeRsp = rsp.msg.CStoreRSP; - rspStatusCode = storeRsp.DimseStatus; - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } - - return cond; -} - + DCMNET_ERROR("Cannot send SOP instance, missing information:"); + if (!dicomFile.isEmpty()) + DCMNET_ERROR(" DICOM Filename : " << dicomFile); + DCMNET_ERROR(" SOP Class UID : " << sopClassUID); + DCMNET_ERROR(" SOP Instance UID : " << sopInstanceUID); + DCMNET_ERROR(" Transfer Syntax : " << xfer.getXferName()); + if (pcid == 0) + DCMNET_ERROR(" Pres. Context ID : 0 (find via SOP Class and Transfer Syntax)"); + else + DCMNET_ERROR(" Pres. Context ID : " << OFstatic_cast(unsigned int, pcid)); + delete fileformat; + return cond; + } + OFStandard::strlcpy(req->AffectedSOPClassUID, sopClassUID.c_str(), sizeof(req->AffectedSOPClassUID)); + OFStandard::strlcpy(req->AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(req->AffectedSOPInstanceUID)); + req->DataSetType = DIMSE_DATASET_PRESENT; + req->Priority = DIMSE_PRIORITY_MEDIUM; + + /* If desired (optional), insert MOVE originator information if this C-STORE + was initiated through a C-MOVE request. + */ + if (!moveOriginatorAETitle.empty()) + { + OFStandard::strlcpy(req->MoveOriginatorApplicationEntityTitle, + moveOriginatorAETitle.c_str(), + sizeof(req->MoveOriginatorApplicationEntityTitle)); + req->opts |= O_STORE_MOVEORIGINATORAETITLE; + } + if (moveOriginatorMsgID != 0) + { + req->MoveOriginatorID = moveOriginatorMsgID; + req->opts |= O_STORE_MOVEORIGINATORID; + } -/* ************************************************************************* */ -/* C-MOVE functionality */ -/* ************************************************************************* */ + /* If no presentation context is specified by the caller ... */ + if (pcid == 0) + { + /* ... try to find an appropriate presentation context automatically */ + pcid = findPresentationContextID(sopClassUID, xfer.getXferID()); + } + else if (m_datasetConversionMode) + { + /* Convert dataset to network transfer syntax (if required) */ + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + /* Check whether given presentation context was accepted by the peer */ + if (abstractSyntax.empty() || transferSyntax.empty()) + { + /* Mark presentation context as invalid */ + pcid = 0; + } + else + { + if (abstractSyntax != sopClassUID) + { + DCMNET_WARN("Inappropriate presentation context with ID " + << OFstatic_cast(unsigned int, pcid) << ": abstract syntax does not match SOP class UID"); + } + /* Try to convert to the negotiated transfer syntax */ + DcmXfer netXfer = DcmXfer(transferSyntax.c_str()).getXfer(); + if (netXfer.getXfer() != xferSyntax) + { + DCMNET_INFO("Converting transfer syntax: " << xfer.getXferName() << " -> " << netXfer.getXferName()); + cond = dataset->chooseRepresentation(netXfer.getXfer(), NULL); + if (cond.bad()) + { + DCMNET_ERROR("No conversion to transfer syntax " << netXfer.getXferName() << " possible!"); + delete fileformat; + return cond; + } + } + } + } + /* No appropriate presentation context for sending */ + if (pcid == 0) + { + OFString sopClassName = dcmFindNameOfUID(sopClassUID.c_str(), sopClassUID.c_str()); + OFString xferName = xfer.getXferName(); + DCMNET_ERROR("No presentation context found for sending C-STORE with SOP Class / Transfer Syntax: " + << sopClassName << " / " << xferName); + delete fileformat; + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + } -// Sends a C-MOVE Request on given presentation context -OFCondition DcmSCU::sendMOVERequest(const T_ASC_PresentationContextID presID, - const OFString &moveDestinationAETitle, - DcmDataset *dataset, - OFList *responses) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (dataset == NULL) - return DIMSE_NULLKEY; - - /* Prepare DIMSE data structures for issuing request */ - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message msg; - // make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - DcmDataset* statusDetail = NULL; - T_DIMSE_C_MoveRQ* req = &(msg.msg.CMoveRQ); - // Set type of message - msg.CommandField = DIMSE_C_MOVE_RQ; - // Set message ID - req->MessageID = nextMessageID(); - // Announce dataset - req->DataSetType = DIMSE_DATASET_PRESENT; - // Set target for embedded C-Store's - OFStandard::strlcpy(req->MoveDestination, moveDestinationAETitle.c_str(), sizeof(req->MoveDestination)); - // Set priority (mandatory) - req->Priority = DIMSE_PRIORITY_MEDIUM; - - /* Determine SOP Class from presentation context */ - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); - - /* Send request */ - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-MOVE Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, dataset, pcid)); - } else { - DCMNET_INFO("Sending C-MOVE Request (MsgID " << req->MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, dataset); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-MOVE request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + /* Send request */ + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-STORE Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); + } + else + { + DCMNET_INFO("Sending C-STORE Request (MsgID " << req->MessageID << ", " + << dcmSOPClassUIDToModality(sopClassUID.c_str(), "OT") << ")"); + } + cond = sendDIMSEMessage(pcid, &msg, dataset); + delete fileformat; + fileformat = NULL; + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-STORE request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - /* Receive and handle C-MOVE response messages */ - OFBool waitForNextResponse = OFTrue; - while (waitForNextResponse) - { + /* Receive response */ T_DIMSE_Message rsp; - // Make sure everything is zeroed, especially options + // Make sure everything is zeroed (especially options) bzero((char*)&rsp, sizeof(rsp)); - statusDetail = NULL; - - // Receive command set cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); if (cond.bad()) { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - delete statusDetail; - break; + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; } - if (rsp.CommandField == DIMSE_C_MOVE_RSP) + if (rsp.CommandField == DIMSE_C_STORE_RSP) { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Received C-MOVE Response"); + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-STORE Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-STORE Response (" << DU_cstoreStatusString(rsp.msg.CStoreRSP.DimseStatus) << ")"); + } + } + else + { + DCMNET_ERROR("Expected C-STORE response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, rsp.CommandField)); DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-MOVE Response (" << DU_cmoveStatusString(rsp.msg.CMoveRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected C-MOVE response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, rsp.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - cond = DIMSE_BADCOMMANDTYPE; - break; - } - - // Prepare response package for response handler - OFunique_ptr moveRSP(new RetrieveResponse); - moveRSP->m_affectedSOPClassUID = rsp.msg.CMoveRSP.AffectedSOPClassUID; - moveRSP->m_messageIDRespondedTo = rsp.msg.CMoveRSP.MessageIDBeingRespondedTo; - moveRSP->m_status = rsp.msg.CMoveRSP.DimseStatus; - moveRSP->m_numberOfRemainingSubops = rsp.msg.CMoveRSP.NumberOfRemainingSubOperations; - moveRSP->m_numberOfCompletedSubops = rsp.msg.CMoveRSP.NumberOfCompletedSubOperations; - moveRSP->m_numberOfFailedSubops = rsp.msg.CMoveRSP.NumberOfFailedSubOperations; - moveRSP->m_numberOfWarningSubops = rsp.msg.CMoveRSP.NumberOfWarningSubOperations; - moveRSP->m_statusDetail = statusDetail; - //DCMNET_DEBUG("C-MOVE response has status 0x" - // << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - // << moveRSP->m_status); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + T_DIMSE_C_StoreRSP storeRsp = rsp.msg.CStoreRSP; + rspStatusCode = storeRsp.DimseStatus; if (statusDetail != NULL) { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; } - // Receive dataset if there is one (status PENDING) - DcmDataset *rspDataset = NULL; - // Check if dataset is announced correctly - if (rsp.msg.CMoveRSP.DataSetType != DIMSE_DATASET_NULL) // Some of the sub operations have failed, thus a dataset with a list of them is attached + return cond; +} + +/* ************************************************************************* */ +/* C-MOVE functionality */ +/* ************************************************************************* */ + +// Sends a C-MOVE Request on given presentation context +OFCondition DcmSCU::sendMOVERequest(const T_ASC_PresentationContextID presID, + const OFString& moveDestinationAETitle, + DcmDataset* dataset, + OFList* responses) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (dataset == NULL) + return DIMSE_NULLKEY; + + /* Prepare DIMSE data structures for issuing request */ + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message msg; + // make sure everything is zeroed (especially options) + bzero((char*)&msg, sizeof(msg)); + DcmDataset* statusDetail = NULL; + T_DIMSE_C_MoveRQ* req = &(msg.msg.CMoveRQ); + // Set type of message + msg.CommandField = DIMSE_C_MOVE_RQ; + // Set message ID + req->MessageID = nextMessageID(); + // Announce dataset + req->DataSetType = DIMSE_DATASET_PRESENT; + // Set target for embedded C-Store's + OFStandard::strlcpy(req->MoveDestination, moveDestinationAETitle.c_str(), sizeof(req->MoveDestination)); + // Set priority (mandatory) + req->Priority = DIMSE_PRIORITY_MEDIUM; + + /* Determine SOP Class from presentation context */ + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); + + /* Send request */ + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { - // Receive dataset - cond = receiveDIMSEDataset(&pcid, &rspDataset); - if (cond.bad()) - { - DCMNET_ERROR("Unable to receive C-MOVE dataset on presentation context " - << OFstatic_cast(unsigned int, pcid) << ": " << DimseCondition::dump(tempStr, cond)); - break; - } - moveRSP->m_dataset = rspDataset; + DCMNET_INFO("Sending C-MOVE Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, dataset, pcid)); } - - // Handle C-MOVE response (has to handle all possible status flags) - cond = handleMOVEResponse(pcid, moveRSP.get(), waitForNextResponse); + else + { + DCMNET_INFO("Sending C-MOVE Request (MsgID " << req->MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &msg, dataset); if (cond.bad()) { - DCMNET_WARN("Unable to handle C-MOVE response correctly: " << cond.text() << " (ignored)"); - // don't return here but trust the "waitForNextResponse" variable + DCMNET_ERROR("Failed sending C-MOVE request: " << DimseCondition::dump(tempStr, cond)); + return cond; } - // if response could be handled successfully, add it to response list - else + + /* Receive and handle C-MOVE response messages */ + OFBool waitForNextResponse = OFTrue; + while (waitForNextResponse) { - if (responses != NULL) // only add if desired by caller - responses->push_back(moveRSP.release()); + T_DIMSE_Message rsp; + // Make sure everything is zeroed, especially options + bzero((char*)&rsp, sizeof(rsp)); + statusDetail = NULL; + + // Receive command set + cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); + if (cond.bad()) + { + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + delete statusDetail; + break; + } + + if (rsp.CommandField == DIMSE_C_MOVE_RSP) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-MOVE Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-MOVE Response (" << DU_cmoveStatusString(rsp.msg.CMoveRSP.DimseStatus) << ")"); + } + } + else + { + DCMNET_ERROR("Expected C-MOVE response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, rsp.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + cond = DIMSE_BADCOMMANDTYPE; + break; + } + + // Prepare response package for response handler + OFunique_ptr moveRSP(new RetrieveResponse); + moveRSP->m_affectedSOPClassUID = rsp.msg.CMoveRSP.AffectedSOPClassUID; + moveRSP->m_messageIDRespondedTo = rsp.msg.CMoveRSP.MessageIDBeingRespondedTo; + moveRSP->m_status = rsp.msg.CMoveRSP.DimseStatus; + moveRSP->m_numberOfRemainingSubops = rsp.msg.CMoveRSP.NumberOfRemainingSubOperations; + moveRSP->m_numberOfCompletedSubops = rsp.msg.CMoveRSP.NumberOfCompletedSubOperations; + moveRSP->m_numberOfFailedSubops = rsp.msg.CMoveRSP.NumberOfFailedSubOperations; + moveRSP->m_numberOfWarningSubops = rsp.msg.CMoveRSP.NumberOfWarningSubOperations; + moveRSP->m_statusDetail = statusDetail; + // DCMNET_DEBUG("C-MOVE response has status 0x" + // << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + // << moveRSP->m_status); + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + } + + // Receive dataset if there is one (status PENDING) + DcmDataset* rspDataset = NULL; + // Check if dataset is announced correctly + if (rsp.msg.CMoveRSP.DataSetType != DIMSE_DATASET_NULL) // Some of the sub operations have failed, thus a + // dataset with a list of them is attached + { + // Receive dataset + cond = receiveDIMSEDataset(&pcid, &rspDataset); + if (cond.bad()) + { + DCMNET_ERROR("Unable to receive C-MOVE dataset on presentation context " + << OFstatic_cast(unsigned int, pcid) << ": " << DimseCondition::dump(tempStr, cond)); + break; + } + moveRSP->m_dataset = rspDataset; + } + + // Handle C-MOVE response (has to handle all possible status flags) + cond = handleMOVEResponse(pcid, moveRSP.get(), waitForNextResponse); + if (cond.bad()) + { + DCMNET_WARN("Unable to handle C-MOVE response correctly: " << cond.text() << " (ignored)"); + // don't return here but trust the "waitForNextResponse" variable + } + // if response could be handled successfully, add it to response list + else + { + if (responses != NULL) // only add if desired by caller + responses->push_back(moveRSP.release()); + } } - } - /* All responses received or break signal occurred */ - return cond; + /* All responses received or break signal occurred */ + return cond; } - // Standard handler for C-MOVE message responses -OFCondition DcmSCU::handleMOVEResponse( const T_ASC_PresentationContextID /* presID */, - RetrieveResponse *response, - OFBool &waitForNextResponse ) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (response == NULL) - return DIMSE_NULLKEY; - - DCMNET_DEBUG("Handling C-MOVE Response"); - switch (response->m_status) { - case STATUS_MOVE_Failed_IdentifierDoesNotMatchSOPClass: - waitForNextResponse = OFFalse; - DCMNET_ERROR("Identifier does not match SOP class in C-MOVE response"); - break; - case STATUS_MOVE_Failed_MoveDestinationUnknown: - waitForNextResponse = OFFalse; - DCMNET_ERROR("Move destination unknown"); - break; - case STATUS_MOVE_Failed_UnableToProcess: - waitForNextResponse = OFFalse; - DCMNET_ERROR("Unable to process C-Move response"); - break; - case STATUS_MOVE_Cancel_SubOperationsTerminatedDueToCancelIndication: - waitForNextResponse = OFFalse; - DCMNET_DEBUG("Suboperations canceled by server due to CANCEL indication"); - break; - case STATUS_MOVE_Warning_SubOperationsCompleteOneOrMoreFailures: - waitForNextResponse = OFFalse; - DCMNET_WARN("Suboperations of C-MOVE completed with one or more failures"); - break; - case STATUS_Pending: - /* in this case the current C-MOVE-RSP indicates that */ - /* there will be some more results */ - waitForNextResponse = OFTrue; - DCMNET_DEBUG("One or more pending C-MOVE responses"); - break; - case STATUS_Success: - /* in this case, we received the last C-MOVE-RSP so there */ - /* will be no other responses we have to wait for. */ - waitForNextResponse = OFFalse; - DCMNET_DEBUG("Received final C-MOVE response, no more C-MOVE responses expected"); - break; - default: - /* in all other cases, don't expect further responses to come */ +OFCondition DcmSCU::handleMOVEResponse(const T_ASC_PresentationContextID /* presID */, + RetrieveResponse* response, + OFBool& waitForNextResponse) +{ waitForNextResponse = OFFalse; - DCMNET_WARN("Status is 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << response->m_status << " (unknown)"); - DCMNET_WARN("Will not wait for further C-MOVE responses"); - break; - } //switch + if (response == NULL) + return DIMSE_NULLKEY; - return EC_Normal; + DCMNET_DEBUG("Handling C-MOVE Response"); + OFString s; + s = DU_cmoveStatusString(response->m_status); + return handleSessionResponseDefault(response->m_status, s, waitForNextResponse); } - /* ************************************************************************* */ /* C-GET and accompanying C-STORE functionality */ /* ************************************************************************* */ // Sends a C-GET Request on given presentation context OFCondition DcmSCU::sendCGETRequest(const T_ASC_PresentationContextID presID, - DcmDataset *dataset, - OFList *responses) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (dataset == NULL) - return DIMSE_NULLKEY; - - /* Prepare DIMSE data structures for issuing request */ - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message msg; - // Make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - T_DIMSE_C_GetRQ* req = &(msg.msg.CGetRQ); - // Set type of message - msg.CommandField = DIMSE_C_GET_RQ; - // Set message ID - req->MessageID = nextMessageID(); - // Announce dataset - req->DataSetType = DIMSE_DATASET_PRESENT; - // Specify priority - req->Priority = DIMSE_PRIORITY_MEDIUM; - - // Determine SOP Class from presentation context - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); - - /* Send request */ - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-GET Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, dataset, pcid)); - } else { - DCMNET_INFO("Sending C-GET Request (MsgID " << req->MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, dataset); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-GET request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + DcmDataset* dataset, + OFList* responses) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (dataset == NULL) + return DIMSE_NULLKEY; - cond = handleCGETSession(pcid, dataset, responses); - return cond; -} + /* Prepare DIMSE data structures for issuing request */ + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message msg; + // Make sure everything is zeroed (especially options) + bzero((char*)&msg, sizeof(msg)); + T_DIMSE_C_GetRQ* req = &(msg.msg.CGetRQ); + // Set type of message + msg.CommandField = DIMSE_C_GET_RQ; + // Set message ID + req->MessageID = nextMessageID(); + // Announce dataset + req->DataSetType = DIMSE_DATASET_PRESENT; + // Specify priority + req->Priority = DIMSE_PRIORITY_MEDIUM; + + // Determine SOP Class from presentation context + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); + + /* Send request */ + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-GET Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, dataset, pcid)); + } + else + { + DCMNET_INFO("Sending C-GET Request (MsgID " << req->MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &msg, dataset); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-GET request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + cond = handleCGETSession(pcid, dataset, responses); + return cond; +} // Does the logic for switching between C-GET Response and C-STORE Requests OFCondition DcmSCU::handleCGETSession(const T_ASC_PresentationContextID /* presID */, - DcmDataset * /* dataset */, - OFList *responses) + DcmDataset* /* dataset */, + OFList* responses) { - OFCondition result; - OFBool continueSession = OFTrue; - OFString tempStr; + OFCondition result; + OFBool continueSession = OFTrue; + OFString tempStr; - // As long we want to continue (usually, as long as we receive more objects, - // i.e. the final C-GET response has not arrived yet) - while (continueSession) - { - T_DIMSE_Message rsp; - // Make sure everything is zeroed (especially options) - bzero((char*)&rsp, sizeof(rsp)); + // As long we want to continue (usually, as long as we receive more objects, + // i.e. the final C-GET response has not arrived yet) + while (continueSession) + { + T_DIMSE_Message rsp; + // Make sure everything is zeroed (especially options) + bzero((char*)&rsp, sizeof(rsp)); - DcmDataset *statusDetail = NULL; - T_ASC_PresentationContextID pcid = 0; + DcmDataset* statusDetail = NULL; + T_ASC_PresentationContextID pcid = 0; - // Receive command set - result = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); - if (result.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE command: " << DimseCondition::dump(tempStr, result)); - delete statusDetail; - break; - } - // Handle C-GET Response - if (rsp.CommandField == DIMSE_C_GET_RSP) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Received C-GET Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-GET Response (" << DU_cgetStatusString(rsp.msg.CGetRSP.DimseStatus) << ")"); - } - // Prepare response package for response handler - OFunique_ptr getRSP(new RetrieveResponse()); - getRSP->m_affectedSOPClassUID = rsp.msg.CGetRSP.AffectedSOPClassUID; - getRSP->m_messageIDRespondedTo = rsp.msg.CGetRSP.MessageIDBeingRespondedTo; - getRSP->m_status = rsp.msg.CGetRSP.DimseStatus; - getRSP->m_numberOfRemainingSubops = rsp.msg.CGetRSP.NumberOfRemainingSubOperations; - getRSP->m_numberOfCompletedSubops = rsp.msg.CGetRSP.NumberOfCompletedSubOperations; - getRSP->m_numberOfFailedSubops = rsp.msg.CGetRSP.NumberOfFailedSubOperations; - getRSP->m_numberOfWarningSubops = rsp.msg.CGetRSP.NumberOfWarningSubOperations; - getRSP->m_statusDetail = statusDetail; - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - statusDetail = NULL; // forget reference to status detail, will be deleted with getRSP - } - result = handleCGETResponse(pcid, getRSP.get(), continueSession); - if (result.bad()) - { - DCMNET_WARN("Unable to handle C-GET response correctly: " << result.text() << " (ignored)"); - // don't return here but trust the "continueSession" variable - } - // if response could be handled successfully, add it to response list - else { - if (responses != NULL) // only add if desired by caller - responses->push_back(getRSP.release()); - } - } - - // Handle C-STORE Request - else if (rsp.CommandField == DIMSE_C_STORE_RQ) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Received C-STORE Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-STORE Request (MsgID " << rsp.msg.CStoreRQ.MessageID << ")"); - } - // Receive dataset if there is one (status PENDING) - DcmDataset *rspDataset = NULL; - // Check if dataset is announced correctly - if (rsp.msg.CStoreRQ.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_WARN("Incoming C-STORE with no dataset, trying to receive one anyway"); - } - Uint16 desiredCStoreReturnStatus = 0; - // handle normal storage mode, i.e. receive in memory and store to disk - if (m_storageMode == DCMSCU_STORAGE_DISK) - { - // Receive dataset - result = receiveDIMSEDataset(&pcid, &rspDataset); + // Receive command set + result = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); if (result.bad()) { - result = DIMSE_NULLKEY; - desiredCStoreReturnStatus = STATUS_STORE_Error_CannotUnderstand; - } else { - result = handleSTORERequest(pcid, rspDataset, continueSession, desiredCStoreReturnStatus); + DCMNET_ERROR("Failed receiving DIMSE command: " << DimseCondition::dump(tempStr, result)); + delete statusDetail; + break; } - } - // handle bit preserving storage mode, i.e. receive directly to disk - else if (m_storageMode == DCMSCU_STORAGE_BIT_PRESERVING) - { - OFString storageFilename; - OFStandard::combineDirAndFilename(storageFilename, m_storageDir, rsp.msg.CStoreRQ.AffectedSOPInstanceUID, OFTrue); - result = handleSTORERequestFile(&pcid, storageFilename, &(rsp.msg.CStoreRQ)); - if (result.good()) + // Handle C-GET Response + if (rsp.CommandField == DIMSE_C_GET_RSP) { - notifyInstanceStored(storageFilename, rsp.msg.CStoreRQ.AffectedSOPClassUID, rsp.msg.CStoreRQ.AffectedSOPInstanceUID); + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-GET Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-GET Response (" << DU_cgetStatusString(rsp.msg.CGetRSP.DimseStatus) << ")"); + } + // Prepare response package for response handler + OFunique_ptr getRSP(new RetrieveResponse()); + getRSP->m_affectedSOPClassUID = rsp.msg.CGetRSP.AffectedSOPClassUID; + getRSP->m_messageIDRespondedTo = rsp.msg.CGetRSP.MessageIDBeingRespondedTo; + getRSP->m_status = rsp.msg.CGetRSP.DimseStatus; + getRSP->m_numberOfRemainingSubops = rsp.msg.CGetRSP.NumberOfRemainingSubOperations; + getRSP->m_numberOfCompletedSubops = rsp.msg.CGetRSP.NumberOfCompletedSubOperations; + getRSP->m_numberOfFailedSubops = rsp.msg.CGetRSP.NumberOfFailedSubOperations; + getRSP->m_numberOfWarningSubops = rsp.msg.CGetRSP.NumberOfWarningSubOperations; + getRSP->m_statusDetail = statusDetail; + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + statusDetail = NULL; // forget reference to status detail, will be deleted with getRSP + } + result = handleCGETResponse(pcid, getRSP.get(), continueSession); + if (result.bad()) + { + DCMNET_WARN("Unable to handle C-GET response correctly: " << result.text() << " (ignored)"); + // don't return here but trust the "continueSession" variable + } + // if response could be handled successfully, add it to response list + else + { + if (responses != NULL) // only add if desired by caller + responses->push_back(getRSP.release()); + } } - } - // handle ignore storage mode, i.e. ignore received dataset and do not store at all - else - { - result = ignoreSTORERequest(pcid, rsp.msg.CStoreRQ); - } - - // Evaluate result from C-STORE request handling and send response - if (result.bad()) - { - desiredCStoreReturnStatus = STATUS_STORE_Error_CannotUnderstand; - continueSession = OFFalse; - } - result = sendSTOREResponse(pcid, desiredCStoreReturnStatus, rsp.msg.CStoreRQ); - if (result.bad()) - { - continueSession = OFFalse; - } - } - - // Handle other DIMSE command (error since other command than GET/STORE not expected) - else - { - DCMNET_ERROR("Expected C-GET response or C-STORE request but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, rsp.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - result = DIMSE_BADCOMMANDTYPE; - continueSession = OFFalse; - } - delete statusDetail; // should be NULL if not existing or added to response list - statusDetail = NULL; - } - /* All responses received or break signal occurred */ + // Handle C-STORE Request + else if (rsp.CommandField == DIMSE_C_STORE_RQ) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-STORE Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-STORE Request (MsgID " << rsp.msg.CStoreRQ.MessageID << ")"); + } + // Receive dataset if there is one (status PENDING) + DcmDataset* rspDataset = NULL; + // Check if dataset is announced correctly + if (rsp.msg.CStoreRQ.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_WARN("Incoming C-STORE with no dataset, trying to receive one anyway"); + } + Uint16 desiredCStoreReturnStatus = 0; + // handle normal storage mode, i.e. receive in memory and store to disk + if (m_storageMode == DCMSCU_STORAGE_DISK) + { + // Receive dataset + result = receiveDIMSEDataset(&pcid, &rspDataset); + if (result.bad()) + { + result = DIMSE_NULLKEY; + desiredCStoreReturnStatus = STATUS_STORE_Error_CannotUnderstand; + } + else + { + result = handleSTORERequest(pcid, rspDataset, continueSession, desiredCStoreReturnStatus); + } + } + // handle bit preserving storage mode, i.e. receive directly to disk + else if (m_storageMode == DCMSCU_STORAGE_BIT_PRESERVING) + { + OFString storageFilename; + OFStandard::combineDirAndFilename( + storageFilename, m_storageDir, rsp.msg.CStoreRQ.AffectedSOPInstanceUID, OFTrue); + result = handleSTORERequestFile(&pcid, storageFilename, &(rsp.msg.CStoreRQ)); + if (result.good()) + { + notifyInstanceStored( + storageFilename, rsp.msg.CStoreRQ.AffectedSOPClassUID, rsp.msg.CStoreRQ.AffectedSOPInstanceUID); + } + } + // handle ignore storage mode, i.e. ignore received dataset and do not store at all + else + { + result = ignoreSTORERequest(pcid, rsp.msg.CStoreRQ); + } + + // Evaluate result from C-STORE request handling and send response + if (result.bad()) + { + desiredCStoreReturnStatus = STATUS_STORE_Error_CannotUnderstand; + continueSession = OFFalse; + } + result = sendSTOREResponse(pcid, desiredCStoreReturnStatus, rsp.msg.CStoreRQ); + if (result.bad()) + { + continueSession = OFFalse; + } + } - return result; + // Handle other DIMSE command (error since other command than GET/STORE not expected) + else + { + DCMNET_ERROR("Expected C-GET response or C-STORE request but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, rsp.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + result = DIMSE_BADCOMMANDTYPE; + continueSession = OFFalse; + } -} + delete statusDetail; // should be NULL if not existing or added to response list + statusDetail = NULL; + } + /* All responses received or break signal occurred */ + return result; +} // Handles single C-GET Response OFCondition DcmSCU::handleCGETResponse(const T_ASC_PresentationContextID /* presID */, RetrieveResponse* response, OFBool& continueCGETSession) { - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (response == NULL) - return DIMSE_NULLKEY; - - DCMNET_DEBUG("Handling C-GET Response"); - - /* First, perform separate check for 0xCxxx error codes */ - Uint16 highNibble = response->m_status & 0xf000; - if (highNibble == STATUS_GET_Failed_UnableToProcess) - { - continueCGETSession = OFFalse; - DCMNET_ERROR("Unable to Process"); - DCMNET_WARN("Full status is 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << response->m_status); - return EC_Normal; - } - - /* Check for other error codes */ - switch (response->m_status) { - case STATUS_GET_Refused_OutOfResourcesNumberOfMatches: - continueCGETSession = OFFalse; - DCMNET_ERROR("Out of Resources - Unable to calculate number of matches"); - break; - case STATUS_GET_Refused_OutOfResourcesSubOperations: - continueCGETSession = OFFalse; - DCMNET_ERROR("Out of Resources - Unable to perform sub-operations"); - break; - case STATUS_GET_Failed_IdentifierDoesNotMatchSOPClass: continueCGETSession = OFFalse; - DCMNET_ERROR("Identifier does not match SOP class"); - break; - case STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication: - continueCGETSession = OFFalse; - DCMNET_DEBUG("Suboperations canceled by server due to CANCEL indication"); - break; - case STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures: - continueCGETSession = OFFalse; - DCMNET_WARN("Suboperations of C-GET completed with one or more failures"); - break; - case STATUS_Pending: - /* in this case the current C-MOVE-RSP indicates that */ - /* there will be some more results */ - continueCGETSession = OFTrue; - DCMNET_DEBUG("One or more pending C-GET responses"); - break; - case STATUS_Success: - /* in this case, we received the last C-MOVE-RSP so there */ - /* will be no other responses we have to wait for. */ - continueCGETSession = OFFalse; - DCMNET_DEBUG("Received final C-GET response, no more C-GET responses expected"); - break; - default: - /* in all other cases, don't expect further responses to come */ - continueCGETSession = OFFalse; - DCMNET_WARN("Status is 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << response->m_status << " (unknown)"); - DCMNET_WARN("Will not wait for further C-GET responses"); - break; - } //switch + if (response == NULL) + return DIMSE_NULLKEY; - return EC_Normal; + DCMNET_DEBUG("Handling C-GET Response"); + OFString s; + s = DU_cgetStatusString(response->m_status); + return handleSessionResponseDefault(response->m_status, s, continueCGETSession); } - // Handles single C-STORE Request received during C-GET session OFCondition DcmSCU::handleSTORERequest(const T_ASC_PresentationContextID /* presID */, - DcmDataset *incomingObject, + DcmDataset* incomingObject, OFBool& /* continueCGETSession */, Uint16& cStoreReturnStatus) { - if (incomingObject == NULL) - return DIMSE_NULLKEY; + if (incomingObject == NULL) + return DIMSE_NULLKEY; - OFString sopClassUID; - OFString sopInstanceUID; - OFCondition result = incomingObject->findAndGetOFString(DCM_SOPClassUID, sopClassUID); - if (result.good()) - result = incomingObject->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID); - if (result.bad()) - { - DCMNET_ERROR("Cannot store received object: either SOP Instance or SOP Class UID not present"); - cStoreReturnStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; - delete incomingObject; - return EC_TagNotFound; - } + OFString sopClassUID; + OFString sopInstanceUID; + OFCondition result = incomingObject->findAndGetOFString(DCM_SOPClassUID, sopClassUID); + if (result.good()) + result = incomingObject->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID); + if (result.bad()) + { + DCMNET_ERROR("Cannot store received object: either SOP Instance or SOP Class UID not present"); + cStoreReturnStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + delete incomingObject; + return EC_TagNotFound; + } - OFString filename = createStorageFilename(incomingObject); - if (OFStandard::fileExists(filename)) - { - DCMNET_WARN("DICOM file already exists, overwriting: " << filename); - } - DcmFileFormat dcmff(incomingObject, OFFalse /* do not copy but take ownership */); - result = dcmff.saveFile(filename); - if (result.good()) - { - E_TransferSyntax xferSyntax; - getDatasetInfo(incomingObject, sopClassUID, sopInstanceUID, xferSyntax); - notifyInstanceStored(filename, sopClassUID, sopInstanceUID); - cStoreReturnStatus = STATUS_Success; - } - else - { - DCMNET_ERROR("cannot write DICOM file: " << filename); - cStoreReturnStatus = STATUS_STORE_Refused_OutOfResources; + OFString filename = createStorageFilename(incomingObject); + if (OFStandard::fileExists(filename)) + { + DCMNET_WARN("DICOM file already exists, overwriting: " << filename); + } + DcmFileFormat dcmff(incomingObject, OFFalse /* do not copy but take ownership */); + result = dcmff.saveFile(filename); + if (result.good()) + { + E_TransferSyntax xferSyntax; + getDatasetInfo(incomingObject, sopClassUID, sopInstanceUID, xferSyntax); + notifyInstanceStored(filename, sopClassUID, sopInstanceUID); + cStoreReturnStatus = STATUS_Success; + } + else + { + DCMNET_ERROR("cannot write DICOM file: " << filename); + cStoreReturnStatus = STATUS_STORE_Refused_OutOfResources; - // delete incomplete file - OFStandard::deleteFile(filename); - } + // delete incomplete file + OFStandard::deleteFile(filename); + } - return result; + return result; } -OFCondition DcmSCU::handleSTORERequestFile(T_ASC_PresentationContextID *presID, - const OFString &filename, - T_DIMSE_C_StoreRQ *request) +OFCondition DcmSCU::handleSTORERequestFile(T_ASC_PresentationContextID* presID, + const OFString& filename, + T_DIMSE_C_StoreRQ* request) { - if (filename.empty()) - return EC_IllegalParameter; + if (filename.empty()) + return EC_IllegalParameter; - /* in the following, we want to receive data over the network and write it to a file */ - /* exactly the way it was received over the network. Hence, a filestream will be created and the data */ - /* set will be received and written to the file through the call to DIMSE_receiveDataSetInFile(...).*/ - /* create filestream */ - DcmOutputFileStream *filestream = NULL; - OFCondition cond = DIMSE_createFilestream(filename, request, m_assoc, *presID, OFTrue, &filestream); - if (cond.good()) - { - if (m_progressNotificationMode) + /* in the following, we want to receive data over the network and write it to a file */ + /* exactly the way it was received over the network. Hence, a filestream will be created and the data */ + /* set will be received and written to the file through the call to DIMSE_receiveDataSetInFile(...).*/ + /* create filestream */ + DcmOutputFileStream* filestream = NULL; + OFCondition cond = DIMSE_createFilestream(filename, request, m_assoc, *presID, OFTrue, &filestream); + if (cond.good()) { - cond = DIMSE_receiveDataSetInFile(m_assoc, m_blockMode, m_dimseTimeout, presID, filestream, - callbackRECEIVEProgress, this /*callbackData*/); - } else { - cond = DIMSE_receiveDataSetInFile(m_assoc, m_blockMode, m_dimseTimeout, presID, filestream, - NULL /*callback*/, NULL /*callbackData*/); + if (m_progressNotificationMode) + { + cond = DIMSE_receiveDataSetInFile(m_assoc, + m_blockMode, + m_dimseTimeout, + presID, + filestream, + callbackRECEIVEProgress, + this /*callbackData*/); + } + else + { + cond = DIMSE_receiveDataSetInFile( + m_assoc, m_blockMode, m_dimseTimeout, presID, filestream, NULL /*callback*/, NULL /*callbackData*/); + } + delete filestream; + if (cond != EC_Normal) + { + OFStandard::deleteFile(filename); + } + DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); } - delete filestream; - if (cond != EC_Normal) + else { - OFStandard::deleteFile(filename); + OFString tempStr; + DCMNET_ERROR("Unable to receive and store dataset on presentation context " + << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); } - DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); - } - else - { - OFString tempStr; - DCMNET_ERROR("Unable to receive and store dataset on presentation context " - << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); - } - return cond; -} - - -OFCondition DcmSCU::sendSTOREResponse(T_ASC_PresentationContextID presID, - Uint16 status, - const T_DIMSE_C_StoreRQ& request) -{ - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); - T_DIMSE_C_StoreRSP &storeRsp = response.msg.CStoreRSP; - response.CommandField = DIMSE_C_STORE_RSP; - storeRsp.MessageIDBeingRespondedTo = request.MessageID; - storeRsp.DimseStatus = status; - storeRsp.DataSetType = DIMSE_DATASET_NULL; - /* Following information is optional and normally not sent by the underlying - * dcmnet routines. However, maybe this could be changed later, so insert it. - */ - OFStandard::strlcpy(storeRsp.AffectedSOPClassUID, request.AffectedSOPClassUID, sizeof(storeRsp.AffectedSOPClassUID)); - OFStandard::strlcpy(storeRsp.AffectedSOPInstanceUID, request.AffectedSOPInstanceUID, sizeof(storeRsp.AffectedSOPInstanceUID)); - storeRsp.opts = O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID; - - OFString tempStr; - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-STORE Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); - } else { - DCMNET_INFO("Sending C-STORE Response (" << DU_cstoreStatusString(status) << ")"); - } - OFCondition cond = sendDIMSEMessage(presID, &response, NULL /*dataObject*/); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-STORE response: " << DimseCondition::dump(tempStr, cond)); - } - return cond; + return cond; } - -OFString DcmSCU::createStorageFilename(DcmDataset *dataset) +OFCondition +DcmSCU::sendSTOREResponse(T_ASC_PresentationContextID presID, Uint16 status, const T_DIMSE_C_StoreRQ& request) { - OFString sopClassUID, sopInstanceUID; - E_TransferSyntax dummy; - getDatasetInfo(dataset, sopClassUID, sopInstanceUID, dummy); - // Create unique filename - if (sopClassUID.empty() || sopInstanceUID.empty()) - return ""; - OFString name = dcmSOPClassUIDToModality(sopClassUID.c_str(), "UNKNOWN"); - name += "."; - name += sopInstanceUID; - OFString returnStr; - OFStandard::combineDirAndFilename(returnStr, m_storageDir, name, OFTrue); - return returnStr; + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); + T_DIMSE_C_StoreRSP& storeRsp = response.msg.CStoreRSP; + response.CommandField = DIMSE_C_STORE_RSP; + storeRsp.MessageIDBeingRespondedTo = request.MessageID; + storeRsp.DimseStatus = status; + storeRsp.DataSetType = DIMSE_DATASET_NULL; + /* Following information is optional and normally not sent by the underlying + * dcmnet routines. However, maybe this could be changed later, so insert it. + */ + OFStandard::strlcpy( + storeRsp.AffectedSOPClassUID, request.AffectedSOPClassUID, sizeof(storeRsp.AffectedSOPClassUID)); + OFStandard::strlcpy( + storeRsp.AffectedSOPInstanceUID, request.AffectedSOPInstanceUID, sizeof(storeRsp.AffectedSOPInstanceUID)); + storeRsp.opts = O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID; + + OFString tempStr; + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-STORE Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); + } + else + { + DCMNET_INFO("Sending C-STORE Response (" << DU_cstoreStatusString(status) << ")"); + } + OFCondition cond = sendDIMSEMessage(presID, &response, NULL /*dataObject*/); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-STORE response: " << DimseCondition::dump(tempStr, cond)); + } + return cond; } +OFString DcmSCU::createStorageFilename(DcmDataset* dataset) +{ + OFString sopClassUID, sopInstanceUID; + E_TransferSyntax dummy; + getDatasetInfo(dataset, sopClassUID, sopInstanceUID, dummy); + // Create unique filename + if (sopClassUID.empty() || sopInstanceUID.empty()) + return ""; + OFString name = dcmSOPClassUIDToModality(sopClassUID.c_str(), "UNKNOWN"); + name += "."; + name += sopInstanceUID; + OFString returnStr; + OFStandard::combineDirAndFilename(returnStr, m_storageDir, name, OFTrue); + return returnStr; +} -OFCondition DcmSCU::ignoreSTORERequest(T_ASC_PresentationContextID presID, - const T_DIMSE_C_StoreRQ &request) +OFCondition DcmSCU::ignoreSTORERequest(T_ASC_PresentationContextID presID, const T_DIMSE_C_StoreRQ& request) { - /* We cannot create the filestream, so ignore the incoming dataset and return an out-of-resources error to the SCU */ - DIC_UL bytesRead = 0; - DIC_UL pdvCount=0; - DCMNET_DEBUG("Ignoring incoming C-STORE dataset on presentation context " - << OFstatic_cast(unsigned int, presID) - << " with Affected SOP Instance UID: " << request.AffectedSOPInstanceUID ); - OFCondition result = DIMSE_ignoreDataSet(m_assoc, m_blockMode, m_dimseTimeout, &bytesRead, &pdvCount); - if (result.good()) - { - DCMNET_TRACE("Successfully skipped " << bytesRead << " bytes in " << pdvCount << " PDVs"); - } - return result; + /* We cannot create the filestream, so ignore the incoming dataset and return an out-of-resources error to the SCU + */ + DIC_UL bytesRead = 0; + DIC_UL pdvCount = 0; + DCMNET_DEBUG("Ignoring incoming C-STORE dataset on presentation context " + << OFstatic_cast(unsigned int, presID) + << " with Affected SOP Instance UID: " << request.AffectedSOPInstanceUID); + OFCondition result = DIMSE_ignoreDataSet(m_assoc, m_blockMode, m_dimseTimeout, &bytesRead, &pdvCount); + if (result.good()) + { + DCMNET_TRACE("Successfully skipped " << bytesRead << " bytes in " << pdvCount << " PDVs"); + } + return result; } - -void DcmSCU::notifyInstanceStored(const OFString &filename, - const OFString &sopClassUID, - const OFString &sopInstanceUID) const +void DcmSCU::notifyInstanceStored(const OFString& filename, + const OFString& sopClassUID, + const OFString& sopInstanceUID) const { - DCMNET_DEBUG("Stored instance to disk:"); - DCMNET_DEBUG(" Filename: " << filename); - DCMNET_DEBUG(" SOP Class UID: " << sopClassUID); - DCMNET_DEBUG(" SOP Instance UID: " << sopInstanceUID); + DCMNET_DEBUG("Stored instance to disk:"); + DCMNET_DEBUG(" Filename: " << filename); + DCMNET_DEBUG(" SOP Class UID: " << sopClassUID); + DCMNET_DEBUG(" SOP Instance UID: " << sopInstanceUID); } - /* ************************************************************************* */ /* C-FIND functionality */ /* ************************************************************************* */ // Sends a C-FIND Request on given presentation context -OFCondition DcmSCU::sendFINDRequest(const T_ASC_PresentationContextID presID, - DcmDataset *queryKeys, - OFList *responses) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (queryKeys == NULL) - return DIMSE_NULLKEY; - - /* Prepare DIMSE data structures for issuing request */ - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message msg; - // Make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - - DcmDataset* statusDetail = NULL; - T_DIMSE_C_FindRQ* req = &(msg.msg.CFindRQ); - // Set type of message - msg.CommandField = DIMSE_C_FIND_RQ; - // Set message ID - req->MessageID = nextMessageID(); - // Announce dataset - req->DataSetType = DIMSE_DATASET_PRESENT; - // Specify priority - req->Priority = DIMSE_PRIORITY_MEDIUM; - - // Determine SOP Class from presentation context - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); - - /* Send request */ - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-FIND Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, queryKeys, pcid)); - } else { - DCMNET_INFO("Sending C-FIND Request (MsgID " << req->MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, queryKeys); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-FIND request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } +OFCondition +DcmSCU::sendFINDRequest(const T_ASC_PresentationContextID presID, DcmDataset* queryKeys, OFList* responses) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (queryKeys == NULL) + return DIMSE_NULLKEY; - /* Receive and handle response */ - OFBool waitForNextResponse = OFTrue; - while (waitForNextResponse) - { - T_DIMSE_Message rsp; + /* Prepare DIMSE data structures for issuing request */ + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message msg; // Make sure everything is zeroed (especially options) - bzero((char*)&rsp, sizeof(rsp)); - - statusDetail = NULL; + bzero((char*)&msg, sizeof(msg)); + + DcmDataset* statusDetail = NULL; + T_DIMSE_C_FindRQ* req = &(msg.msg.CFindRQ); + // Set type of message + msg.CommandField = DIMSE_C_FIND_RQ; + // Set message ID + req->MessageID = nextMessageID(); + // Announce dataset + req->DataSetType = DIMSE_DATASET_PRESENT; + // Specify priority + req->Priority = DIMSE_PRIORITY_MEDIUM; + + // Determine SOP Class from presentation context + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy(req->AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(req->AffectedSOPClassUID)); - // Receive command set - cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); - if (cond.bad()) + /* Send request */ + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; + DCMNET_INFO("Sending C-FIND Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, queryKeys, pcid)); } - - if (rsp.CommandField == DIMSE_C_FIND_RSP) + else { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Received C-FIND Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received C-FIND Response (" << DU_cfindStatusString(rsp.msg.CFindRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected C-FIND response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, rsp.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - - // Prepare response package for response handler - OFunique_ptr findRSP(new QRResponse); - findRSP->m_affectedSOPClassUID = rsp.msg.CFindRSP.AffectedSOPClassUID; - findRSP->m_messageIDRespondedTo = rsp.msg.CFindRSP.MessageIDBeingRespondedTo; - findRSP->m_status = rsp.msg.CFindRSP.DimseStatus; - findRSP->m_statusDetail = statusDetail; - - // Receive dataset if there is one (status PENDING) - DcmDataset *rspDataset = NULL; - if (DICOM_PENDING_STATUS(findRSP->m_status)) - { - // Check if dataset is announced correctly - if (rsp.msg.CFindRSP.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_ERROR("Received C-FIND response with PENDING status but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } - - // Receive dataset - cond = receiveDIMSEDataset(&pcid, &rspDataset); - if (cond.bad()) - return DIMSE_BADDATA; - findRSP->m_dataset = rspDataset; + DCMNET_INFO("Sending C-FIND Request (MsgID " << req->MessageID << ")"); } - - // Handle C-FIND response (has to handle all possible status flags) - cond = handleFINDResponse(pcid, findRSP.get(), waitForNextResponse); + cond = sendDIMSEMessage(pcid, &msg, queryKeys); if (cond.bad()) { - DCMNET_WARN("Unable to handle C-FIND response correctly: " << cond.text() << " (ignored)"); - // don't return here but trust the "waitForNextResponse" variable + DCMNET_ERROR("Failed sending C-FIND request: " << DimseCondition::dump(tempStr, cond)); + return cond; } - // if response could be handled successfully, add it to response list - else + + /* Receive and handle response */ + OFBool waitForNextResponse = OFTrue; + while (waitForNextResponse) { - if (responses != NULL) // only add if desired by caller - responses->push_back(findRSP.release()); + T_DIMSE_Message rsp; + // Make sure everything is zeroed (especially options) + bzero((char*)&rsp, sizeof(rsp)); + + statusDetail = NULL; + + // Receive command set + cond = receiveDIMSECommand(&pcid, &rsp, &statusDetail, NULL /* not interested in the command set */); + if (cond.bad()) + { + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + + if (rsp.CommandField == DIMSE_C_FIND_RSP) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received C-FIND Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received C-FIND Response (" << DU_cfindStatusString(rsp.msg.CFindRSP.DimseStatus) << ")"); + } + } + else + { + DCMNET_ERROR("Expected C-FIND response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, rsp.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + + // Prepare response package for response handler + OFunique_ptr findRSP(new QRResponse); + findRSP->m_affectedSOPClassUID = rsp.msg.CFindRSP.AffectedSOPClassUID; + findRSP->m_messageIDRespondedTo = rsp.msg.CFindRSP.MessageIDBeingRespondedTo; + findRSP->m_status = rsp.msg.CFindRSP.DimseStatus; + findRSP->m_statusDetail = statusDetail; + + // Receive dataset if there is one (status PENDING) + DcmDataset* rspDataset = NULL; + if (DICOM_PENDING_STATUS(findRSP->m_status)) + { + // Check if dataset is announced correctly + if (rsp.msg.CFindRSP.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_ERROR("Received C-FIND response with PENDING status but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } + + // Receive dataset + cond = receiveDIMSEDataset(&pcid, &rspDataset); + if (cond.bad()) + return DIMSE_BADDATA; + findRSP->m_dataset = rspDataset; + } + + // Handle C-FIND response (has to handle all possible status flags) + cond = handleFINDResponse(pcid, findRSP.get(), waitForNextResponse); + if (cond.bad()) + { + DCMNET_WARN("Unable to handle C-FIND response correctly: " << cond.text() << " (ignored)"); + // don't return here but trust the "waitForNextResponse" variable + } + // if response could be handled successfully, add it to response list + else + { + if (responses != NULL) // only add if desired by caller + responses->push_back(findRSP.release()); + } } - } - /* All responses received or break signal occurred */ - return EC_Normal; + /* All responses received or break signal occurred */ + return EC_Normal; } - // Standard handler for C-FIND message responses OFCondition DcmSCU::handleFINDResponse(const T_ASC_PresentationContextID /* presID */, - QRResponse *response, - OFBool &waitForNextResponse) -{ - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (response == NULL) - return DIMSE_NULLKEY; - - DCMNET_DEBUG("Handling C-FIND Response"); - switch (response->m_status) { - case STATUS_Pending: - case STATUS_FIND_Pending_WarningUnsupportedOptionalKeys: - /* in this case the current C-FIND-RSP indicates that */ - /* there will be some more results */ - waitForNextResponse = OFTrue; - DCMNET_DEBUG("One or more pending C-FIND responses"); - break; - case STATUS_Success: - /* in this case the current C-FIND-RSP indicates that */ - /* there are no more records that match the search mask */ - waitForNextResponse = OFFalse; - DCMNET_DEBUG("Received final C-FIND response, no more C-FIND responses expected"); - break; - default: - /* in all other cases, don't expect further responses to come */ - waitForNextResponse = OFFalse; - DCMNET_DEBUG("Status tells not to wait for further C-FIND responses"); - break; - } //switch - return EC_Normal; -} + QRResponse* response, + OFBool& waitForNextResponse) +{ + waitForNextResponse = OFFalse; + if (response == NULL) + return DIMSE_NULLKEY; + DCMNET_DEBUG("Handling C-FIND Response"); + OFString s; + s = DU_cfindStatusString(response->m_status); + return handleSessionResponseDefault(response->m_status, s, waitForNextResponse); +} /* ************************************************************************* */ /* C-CANCEL functionality */ @@ -1692,56 +1612,57 @@ OFCondition DcmSCU::handleFINDResponse(const T_ASC_PresentationContextID /* pres // Send C-CANCEL-REQ and, therefore, ends current C-FIND, -MOVE or -GET session OFCondition DcmSCU::sendCANCELRequest(const T_ASC_PresentationContextID presID) { - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - - /* Prepare DIMSE data structures for issuing request */ - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message msg; - // Make sure everything is zeroed (especially options) - bzero((char*)&msg, sizeof(msg)); - T_DIMSE_C_CancelRQ* req = &(msg.msg.CCancelRQ); - // Set type of message - msg.CommandField = DIMSE_C_CANCEL_RQ; - /* Set message ID responded to. A new message ID is _not_ needed so - we do not increment the message ID here but instead have to give the - message ID that was used last. - Note that that it is required to actually use the message ID of the last - C-FIND/GET/MOVE that was issued on this presentation context channel. - However, since we only support synchronous association mode so far, - it is enough to take the last message ID used at all. - For asynchronous operation, we would have to lookup the message ID - of the last C-FIND/GET/MOVE request issued and thus, store this - information after sending it. - */ - req->MessageIDBeingRespondedTo = m_assoc->nextMsgID - 1; - // Announce dataset - req->DataSetType = DIMSE_DATASET_NULL; - - /* We do not care about the transfer syntax since no - dataset is transported at all, i.e. we trust that the user provided - the correct presentation context ID (could be private one). - */ - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending C-CANCEL Request"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending C-CANCEL Request (MsgID " << req->MessageIDBeingRespondedTo - << ", PresID " << OFstatic_cast(unsigned int, pcid) << ")"); - } - cond = sendDIMSEMessage(pcid, &msg, NULL /*dataObject*/); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending C-CANCEL request: " << DimseCondition::dump(tempStr, cond)); - } + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - DCMNET_TRACE("There is no C-CANCEL response in DICOM, so none expected"); - return cond; -} + /* Prepare DIMSE data structures for issuing request */ + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message msg; + // Make sure everything is zeroed (especially options) + bzero((char*)&msg, sizeof(msg)); + T_DIMSE_C_CancelRQ* req = &(msg.msg.CCancelRQ); + // Set type of message + msg.CommandField = DIMSE_C_CANCEL_RQ; + /* Set message ID responded to. A new message ID is _not_ needed so + we do not increment the message ID here but instead have to give the + message ID that was used last. + Note that that it is required to actually use the message ID of the last + C-FIND/GET/MOVE that was issued on this presentation context channel. + However, since we only support synchronous association mode so far, + it is enough to take the last message ID used at all. + For asynchronous operation, we would have to lookup the message ID + of the last C-FIND/GET/MOVE request issued and thus, store this + information after sending it. + */ + req->MessageIDBeingRespondedTo = m_assoc->nextMsgID - 1; + // Announce dataset + req->DataSetType = DIMSE_DATASET_NULL; + + /* We do not care about the transfer syntax since no + dataset is transported at all, i.e. we trust that the user provided + the correct presentation context ID (could be private one). + */ + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending C-CANCEL Request"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, msg, DIMSE_OUTGOING, NULL, pcid)); + } + else + { + DCMNET_INFO("Sending C-CANCEL Request (MsgID " << req->MessageIDBeingRespondedTo << ", PresID " + << OFstatic_cast(unsigned int, pcid) << ")"); + } + cond = sendDIMSEMessage(pcid, &msg, NULL /*dataObject*/); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending C-CANCEL request: " << DimseCondition::dump(tempStr, cond)); + } + DCMNET_TRACE("There is no C-CANCEL response in DICOM, so none expected"); + return cond; +} /* ************************************************************************* */ /* N-ACTION functionality */ @@ -1749,392 +1670,444 @@ OFCondition DcmSCU::sendCANCELRequest(const T_ASC_PresentationContextID presID) // Sends N-ACTION request to another DICOM application OFCondition DcmSCU::sendACTIONRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, + const OFString& sopInstanceUID, const Uint16 actionTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (sopInstanceUID.empty() || (reqDataset == NULL)) - return DIMSE_NULLKEY; - - // Prepare DIMSE data structures for issuing request - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message request; - // Make sure everything is zeroed (especially options) - bzero((char*)&request, sizeof(request)); - T_DIMSE_N_ActionRQ &actionReq = request.msg.NActionRQ; - DcmDataset *statusDetail = NULL; - - request.CommandField = DIMSE_N_ACTION_RQ; - actionReq.MessageID = nextMessageID(); - actionReq.DataSetType = DIMSE_DATASET_PRESENT; - actionReq.ActionTypeID = actionTypeID; - - // Determine SOP Class from presentation context - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(actionReq.RequestedSOPClassUID, abstractSyntax.c_str(), sizeof(actionReq.RequestedSOPClassUID)); - OFStandard::strlcpy(actionReq.RequestedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(actionReq.RequestedSOPInstanceUID)); - - // Send request - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-ACTION Request"); - // Output dataset only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); + DcmDataset* reqDataset, + Uint16& rspStatusCode) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (sopInstanceUID.empty() || (reqDataset == NULL)) + return DIMSE_NULLKEY; + + // Prepare DIMSE data structures for issuing request + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message request; + // Make sure everything is zeroed (especially options) + bzero((char*)&request, sizeof(request)); + T_DIMSE_N_ActionRQ& actionReq = request.msg.NActionRQ; + DcmDataset* statusDetail = NULL; + + request.CommandField = DIMSE_N_ACTION_RQ; + actionReq.MessageID = nextMessageID(); + actionReq.DataSetType = DIMSE_DATASET_PRESENT; + actionReq.ActionTypeID = actionTypeID; + + // Determine SOP Class from presentation context + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy(actionReq.RequestedSOPClassUID, abstractSyntax.c_str(), sizeof(actionReq.RequestedSOPClassUID)); + OFStandard::strlcpy( + actionReq.RequestedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(actionReq.RequestedSOPInstanceUID)); + + // Send request + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending N-ACTION Request"); + // Output dataset only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); + } else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending N-ACTION Request (MsgID " << actionReq.MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &request, reqDataset); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-ACTION request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + { + DCMNET_INFO("Sending N-ACTION Request (MsgID " << actionReq.MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &request, reqDataset); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-ACTION request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - // Receive response - T_DIMSE_Message response; - bzero((char*)&response, sizeof(response)); - cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); - if (cond.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + // Receive response + T_DIMSE_Message response; + bzero((char*)&response, sizeof(response)); + cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); + if (cond.bad()) + { + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - // Check command set - if (response.CommandField == DIMSE_N_ACTION_RSP) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + // Check command set + if (response.CommandField == DIMSE_N_ACTION_RSP) { - DCMNET_INFO("Received N-ACTION Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received N-ACTION Response (" << DU_nactionStatusString(response.msg.NActionRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected N-ACTION response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, response.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received N-ACTION Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received N-ACTION Response (" << DU_nactionStatusString(response.msg.NActionRSP.DimseStatus) + << ")"); + } + } + else + { + DCMNET_ERROR("Expected N-ACTION response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, response.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } - // Set return value - T_DIMSE_N_ActionRSP &actionRsp = response.msg.NActionRSP; - rspStatusCode = actionRsp.DimseStatus; + // Set return value + T_DIMSE_N_ActionRSP& actionRsp = response.msg.NActionRSP; + rspStatusCode = actionRsp.DimseStatus; - // Check whether there is a dataset to be received - if (actionRsp.DataSetType == DIMSE_DATASET_PRESENT) - { - // this should never happen - DcmDataset *tempDataset = NULL; - T_ASC_PresentationContextID tempID; - DCMNET_WARN("Trying to retrieve unexpected dataset in N-ACTION response"); - cond = receiveDIMSEDataset(&tempID, &tempDataset); - if (cond.good()) + // Check whether there is a dataset to be received + if (actionRsp.DataSetType == DIMSE_DATASET_PRESENT) + { + // this should never happen + DcmDataset* tempDataset = NULL; + T_ASC_PresentationContextID tempID; + DCMNET_WARN("Trying to retrieve unexpected dataset in N-ACTION response"); + cond = receiveDIMSEDataset(&tempID, &tempDataset); + if (cond.good()) + { + DCMNET_WARN("Received unexpected dataset after N-ACTION response, ignoring"); + delete tempDataset; + } + else + { + return DIMSE_BADDATA; + } + } + if (actionRsp.MessageIDBeingRespondedTo != actionReq.MessageID) { - DCMNET_WARN("Received unexpected dataset after N-ACTION response, ignoring"); - delete tempDataset; - } else { - return DIMSE_BADDATA; + // since we only support synchronous communication, the message ID in the response + // should be identical to the one in the request + DCMNET_ERROR("Received response with wrong message ID (" << actionRsp.MessageIDBeingRespondedTo + << " instead of " << actionReq.MessageID << ")"); + return DIMSE_BADMESSAGE; } - } - if (actionRsp.MessageIDBeingRespondedTo != actionReq.MessageID) - { - // since we only support synchronous communication, the message ID in the response - // should be identical to the one in the request - DCMNET_ERROR("Received response with wrong message ID (" << actionRsp.MessageIDBeingRespondedTo - << " instead of " << actionReq.MessageID << ")"); - return DIMSE_BADMESSAGE; - } - return cond; + return cond; } - /* ************************************************************************* */ /* N-EVENT REPORT functionality */ /* ************************************************************************* */ // Sends N-EVENT-REPORT request and receives N-EVENT-REPORT response OFCondition DcmSCU::sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID, - const OFString &sopInstanceUID, + const OFString& sopInstanceUID, const Uint16 eventTypeID, - DcmDataset *reqDataset, - Uint16 &rspStatusCode) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (sopInstanceUID.empty() || (reqDataset == NULL)) - return DIMSE_NULLKEY; - - // Prepare DIMSE data structures for issuing request - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID pcid = presID; - T_DIMSE_Message request; - // Make sure everything is zeroed (especially options) - bzero((char*)&request, sizeof(request)); - - T_DIMSE_N_EventReportRQ &eventReportReq = request.msg.NEventReportRQ; - DcmDataset *statusDetail = NULL; - - request.CommandField = DIMSE_N_EVENT_REPORT_RQ; - - // Generate a new message ID - eventReportReq.MessageID = nextMessageID(); - eventReportReq.DataSetType = DIMSE_DATASET_PRESENT; - eventReportReq.EventTypeID = eventTypeID; - - // Determine SOP Class from presentation context - OFString abstractSyntax, transferSyntax; - findPresentationContext(pcid, abstractSyntax, transferSyntax); - if (abstractSyntax.empty() || transferSyntax.empty()) - return DIMSE_NOVALIDPRESENTATIONCONTEXTID; - OFStandard::strlcpy(eventReportReq.AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(eventReportReq.AffectedSOPClassUID)); - OFStandard::strlcpy(eventReportReq.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(eventReportReq.AffectedSOPInstanceUID)); - - // Send request - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-EVENT-REPORT Request"); - // Output dataset only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); - } else { - DCMNET_INFO("Sending N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); - } - cond = sendDIMSEMessage(pcid, &request, reqDataset); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-EVENT-REPORT request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } - // Receive response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); + DcmDataset* reqDataset, + Uint16& rspStatusCode) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (sopInstanceUID.empty() || (reqDataset == NULL)) + return DIMSE_NULLKEY; - cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); - if (cond.bad()) - { - DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); - return cond; - } + // Prepare DIMSE data structures for issuing request + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID pcid = presID; + T_DIMSE_Message request; + // Make sure everything is zeroed (especially options) + bzero((char*)&request, sizeof(request)); - // Check command set - if (response.CommandField == DIMSE_N_EVENT_REPORT_RSP) - { + T_DIMSE_N_EventReportRQ& eventReportReq = request.msg.NEventReportRQ; + DcmDataset* statusDetail = NULL; + + request.CommandField = DIMSE_N_EVENT_REPORT_RQ; + + // Generate a new message ID + eventReportReq.MessageID = nextMessageID(); + eventReportReq.DataSetType = DIMSE_DATASET_PRESENT; + eventReportReq.EventTypeID = eventTypeID; + + // Determine SOP Class from presentation context + OFString abstractSyntax, transferSyntax; + findPresentationContext(pcid, abstractSyntax, transferSyntax); + if (abstractSyntax.empty() || transferSyntax.empty()) + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + OFStandard::strlcpy( + eventReportReq.AffectedSOPClassUID, abstractSyntax.c_str(), sizeof(eventReportReq.AffectedSOPClassUID)); + OFStandard::strlcpy( + eventReportReq.AffectedSOPInstanceUID, sopInstanceUID.c_str(), sizeof(eventReportReq.AffectedSOPInstanceUID)); + + // Send request if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { - DCMNET_INFO("Received N-EVENT-REPORT Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - } else { - DCMNET_INFO("Received N-EVENT-REPORT Response (" << DU_neventReportStatusString(response.msg.NEventReportRSP.DimseStatus) << ")"); - } - } else { - DCMNET_ERROR("Expected N-EVENT-REPORT response but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, response.CommandField)); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - if (statusDetail != NULL) - { - DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } + DCMNET_INFO("Sending N-EVENT-REPORT Request"); + // Output dataset only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, reqDataset, pcid)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_OUTGOING, NULL, pcid)); + } + else + { + DCMNET_INFO("Sending N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); + } + cond = sendDIMSEMessage(pcid, &request, reqDataset); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-EVENT-REPORT request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } + // Receive response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); - // Set return value - T_DIMSE_N_EventReportRSP &eventReportRsp = response.msg.NEventReportRSP; - rspStatusCode = eventReportRsp.DimseStatus; + cond = receiveDIMSECommand(&pcid, &response, &statusDetail, NULL /* commandSet */); + if (cond.bad()) + { + DCMNET_ERROR("Failed receiving DIMSE response: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - // Check whether there is a dataset to be received - if (eventReportRsp.DataSetType == DIMSE_DATASET_PRESENT) - { - // this should never happen - DcmDataset *tempDataset = NULL; - T_ASC_PresentationContextID tempID; - cond = receiveDIMSEDataset(&tempID, &tempDataset); - if (cond.good()) + // Check command set + if (response.CommandField == DIMSE_N_EVENT_REPORT_RSP) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Received N-EVENT-REPORT Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + } + else + { + DCMNET_INFO("Received N-EVENT-REPORT Response (" + << DU_neventReportStatusString(response.msg.NEventReportRSP.DimseStatus) << ")"); + } + } + else { - DCMNET_WARN("Received unexpected dataset after N-EVENT-REPORT response, ignoring"); - delete tempDataset; - } else { - DCMNET_ERROR("Failed receiving unexpected dataset after N-EVENT-REPORT response: " - << DimseCondition::dump(tempStr, cond)); - return DIMSE_BADDATA; + DCMNET_ERROR("Expected N-EVENT-REPORT response but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, response.CommandField)); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_INCOMING, NULL, pcid)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + if (statusDetail != NULL) + { + DCMNET_DEBUG("Response has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; } - } - // Check whether the message ID being responded to is equal to the message ID of the request - if (eventReportRsp.MessageIDBeingRespondedTo != eventReportReq.MessageID) - { - DCMNET_ERROR("Received response with wrong message ID (" << eventReportRsp.MessageIDBeingRespondedTo - << " instead of " << eventReportReq.MessageID << ")"); - return DIMSE_BADMESSAGE; - } - return cond; + // Set return value + T_DIMSE_N_EventReportRSP& eventReportRsp = response.msg.NEventReportRSP; + rspStatusCode = eventReportRsp.DimseStatus; + + // Check whether there is a dataset to be received + if (eventReportRsp.DataSetType == DIMSE_DATASET_PRESENT) + { + // this should never happen + DcmDataset* tempDataset = NULL; + T_ASC_PresentationContextID tempID; + cond = receiveDIMSEDataset(&tempID, &tempDataset); + if (cond.good()) + { + DCMNET_WARN("Received unexpected dataset after N-EVENT-REPORT response, ignoring"); + delete tempDataset; + } + else + { + DCMNET_ERROR("Failed receiving unexpected dataset after N-EVENT-REPORT response: " + << DimseCondition::dump(tempStr, cond)); + return DIMSE_BADDATA; + } + } + + // Check whether the message ID being responded to is equal to the message ID of the request + if (eventReportRsp.MessageIDBeingRespondedTo != eventReportReq.MessageID) + { + DCMNET_ERROR("Received response with wrong message ID (" << eventReportRsp.MessageIDBeingRespondedTo + << " instead of " << eventReportReq.MessageID << ")"); + return DIMSE_BADMESSAGE; + } + return cond; } // Receives N-EVENT-REPORT request -OFCondition DcmSCU::handleEVENTREPORTRequest(DcmDataset *&reqDataset, - Uint16 &eventTypeID, - const int timeout) -{ - // Do some basic validity checks - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - - OFCondition cond; - OFString tempStr; - T_ASC_PresentationContextID presID; - T_ASC_PresentationContextID presIDdset; - T_DIMSE_Message request; - // Make sure everything is zeroed (especially options) - bzero((char*)&request, sizeof(request)); - T_DIMSE_N_EventReportRQ &eventReportReq = request.msg.NEventReportRQ; - DcmDataset *dataset = NULL; - DcmDataset *statusDetail = NULL; - Uint16 statusCode = 0; - - if (timeout > 0) - DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting up to " << timeout << " seconds (only for N-EVENT-REPORT message)"); - else if ((m_dimseTimeout > 0) && (m_blockMode == DIMSE_NONBLOCKING)) - DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting up to " << m_dimseTimeout << " seconds (default for all DIMSE messages)"); - else - DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting an unlimited period of time"); - - // Receive request, use specific timeout (if defined) - cond = receiveDIMSECommand(&presID, &request, &statusDetail, NULL /* commandSet */, timeout); - if (cond.bad()) - { - if (cond != DIMSE_NODATAAVAILABLE) - DCMNET_ERROR("Failed receiving DIMSE request: " << DimseCondition::dump(tempStr, cond)); - return cond; - } +OFCondition DcmSCU::handleEVENTREPORTRequest(DcmDataset*& reqDataset, Uint16& eventTypeID, const int timeout) +{ + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - // Check command set - if (request.CommandField == DIMSE_N_EVENT_REPORT_RQ) - { - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - DCMNET_INFO("Received N-EVENT-REPORT Request"); + OFCondition cond; + OFString tempStr; + T_ASC_PresentationContextID presID; + T_ASC_PresentationContextID presIDdset; + T_DIMSE_Message request; + // Make sure everything is zeroed (especially options) + bzero((char*)&request, sizeof(request)); + T_DIMSE_N_EventReportRQ& eventReportReq = request.msg.NEventReportRQ; + DcmDataset* dataset = NULL; + DcmDataset* statusDetail = NULL; + Uint16 statusCode = 0; + + if (timeout > 0) + DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting up to " << timeout + << " seconds (only for N-EVENT-REPORT message)"); + else if ((m_dimseTimeout > 0) && (m_blockMode == DIMSE_NONBLOCKING)) + DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting up to " << m_dimseTimeout + << " seconds (default for all DIMSE messages)"); else - DCMNET_INFO("Received N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); - } else { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Expected N-EVENT-REPORT request but received DIMSE command 0x" - << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) - << OFstatic_cast(unsigned int, request.CommandField)); - delete statusDetail; - return DIMSE_BADCOMMANDTYPE; - } - if (statusDetail != NULL) - { - DCMNET_DEBUG("Request has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); - delete statusDetail; - } + DCMNET_DEBUG("Handle N-EVENT-REPORT request, waiting an unlimited period of time"); - // Check if dataset is announced correctly - if (eventReportReq.DataSetType == DIMSE_DATASET_NULL) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); - DCMNET_ERROR("Received N-EVENT-REPORT request but no dataset announced, aborting"); - return DIMSE_BADMESSAGE; - } + // Receive request, use specific timeout (if defined) + cond = receiveDIMSECommand(&presID, &request, &statusDetail, NULL /* commandSet */, timeout); + if (cond.bad()) + { + if (cond != DIMSE_NODATAAVAILABLE) + DCMNET_ERROR("Failed receiving DIMSE request: " << DimseCondition::dump(tempStr, cond)); + return cond; + } - // Receive dataset - cond = receiveDIMSEDataset(&presIDdset, &dataset); - if (cond.bad()) - { - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); - return DIMSE_BADDATA; - } + // Check command set + if (request.CommandField == DIMSE_N_EVENT_REPORT_RQ) + { + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + DCMNET_INFO("Received N-EVENT-REPORT Request"); + else + DCMNET_INFO("Received N-EVENT-REPORT Request (MsgID " << eventReportReq.MessageID << ")"); + } + else + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Expected N-EVENT-REPORT request but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned int, request.CommandField)); + delete statusDetail; + return DIMSE_BADCOMMANDTYPE; + } + if (statusDetail != NULL) + { + DCMNET_DEBUG("Request has status detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } - // Output dataset only if trace level is enabled - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, dataset, presID)); - else - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); + // Check if dataset is announced correctly + if (eventReportReq.DataSetType == DIMSE_DATASET_NULL) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); + DCMNET_ERROR("Received N-EVENT-REPORT request but no dataset announced, aborting"); + return DIMSE_BADMESSAGE; + } - // Compare presentation context ID of command and data set - if (presIDdset != presID) - { - DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) - << ") and data set (" << OFstatic_cast(unsigned int, presIDdset) << ") differ"); - delete dataset; - return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, - "DIMSE: Presentation Contexts of Command and Data Set differ"); - } + // Receive dataset + cond = receiveDIMSEDataset(&presIDdset, &dataset); + if (cond.bad()) + { + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); + return DIMSE_BADDATA; + } - // Check the request dataset and return the DIMSE status code to be used - statusCode = checkEVENTREPORTRequest(eventReportReq, dataset); + // Output dataset only if trace level is enabled + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::TRACE_LOG_LEVEL)) + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, dataset, presID)); + else + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID)); - // Send back response - T_DIMSE_Message response; - // Make sure everything is zeroed (especially options) - bzero((char*)&response, sizeof(response)); + // Compare presentation context ID of command and data set + if (presIDdset != presID) + { + DCMNET_ERROR("Presentation Context ID of command (" << OFstatic_cast(unsigned int, presID) << ") and data set (" + << OFstatic_cast(unsigned int, presIDdset) << ") differ"); + delete dataset; + return makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, + OF_error, + "DIMSE: Presentation Contexts of Command and Data Set differ"); + } - T_DIMSE_N_EventReportRSP &eventReportRsp = response.msg.NEventReportRSP; - response.CommandField = DIMSE_N_EVENT_REPORT_RSP; - eventReportRsp.MessageIDBeingRespondedTo = eventReportReq.MessageID; - eventReportRsp.DimseStatus = statusCode; - eventReportRsp.DataSetType = DIMSE_DATASET_NULL; - eventReportRsp.opts = 0; - eventReportRsp.AffectedSOPClassUID[0] = 0; - eventReportRsp.AffectedSOPInstanceUID[0] = 0; + // Check the request dataset and return the DIMSE status code to be used + statusCode = checkEVENTREPORTRequest(eventReportReq, dataset); - if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) - { - DCMNET_INFO("Sending N-EVENT-REPORT Response"); - DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); - } else { - DCMNET_INFO("Sending N-EVENT-REPORT Response (" << DU_neventReportStatusString(statusCode) << ")"); - } - cond = sendDIMSEMessage(presID, &response, NULL /*dataObject*/); - if (cond.bad()) - { - DCMNET_ERROR("Failed sending N-EVENT-REPORT response: " << DimseCondition::dump(tempStr, cond)); - delete dataset; - return cond; - } + // Send back response + T_DIMSE_Message response; + // Make sure everything is zeroed (especially options) + bzero((char*)&response, sizeof(response)); - // Set return values - reqDataset = dataset; - eventTypeID = eventReportReq.EventTypeID; + T_DIMSE_N_EventReportRSP& eventReportRsp = response.msg.NEventReportRSP; + response.CommandField = DIMSE_N_EVENT_REPORT_RSP; + eventReportRsp.MessageIDBeingRespondedTo = eventReportReq.MessageID; + eventReportRsp.DimseStatus = statusCode; + eventReportRsp.DataSetType = DIMSE_DATASET_NULL; + eventReportRsp.opts = 0; + eventReportRsp.AffectedSOPClassUID[0] = 0; + eventReportRsp.AffectedSOPInstanceUID[0] = 0; - return cond; -} + if (DCM_dcmnetLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + DCMNET_INFO("Sending N-EVENT-REPORT Response"); + DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, response, DIMSE_OUTGOING, NULL, presID)); + } + else + { + DCMNET_INFO("Sending N-EVENT-REPORT Response (" << DU_neventReportStatusString(statusCode) << ")"); + } + cond = sendDIMSEMessage(presID, &response, NULL /*dataObject*/); + if (cond.bad()) + { + DCMNET_ERROR("Failed sending N-EVENT-REPORT response: " << DimseCondition::dump(tempStr, cond)); + delete dataset; + return cond; + } + // Set return values + reqDataset = dataset; + eventTypeID = eventReportReq.EventTypeID; + + return cond; +} -Uint16 DcmSCU::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ & /*eventReportReq*/, - DcmDataset * /*reqDataset*/) +Uint16 DcmSCU::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ& /*eventReportReq*/, DcmDataset* /*reqDataset*/) { - // we default to success - return STATUS_Success; + // we default to success + return STATUS_Success; } +OFCondition +DcmSCU::handleSessionResponseDefault(const Uint16 dimseStatus, const OFString& message, OFBool& waitForNextResponse) +{ + waitForNextResponse = OFFalse; + + // Do some basic validity checks + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + + if (DICOM_WARNING_STATUS(dimseStatus)) + { + DCMNET_WARN("DIMSE status is: " << message); + } + else if (DICOM_PENDING_STATUS(dimseStatus)) + { + waitForNextResponse = OFTrue; + DCMNET_DEBUG("DIMSE status is: " << message); + } + else if (dimseStatus == STATUS_Success) + { + DCMNET_DEBUG("DIMSE status is: " << message); + } + else + { + DCMNET_ERROR("DIMSE status is: " << message); + } + + return EC_Normal; +} /* ************************************************************************* */ /* General message handling */ @@ -2142,41 +2115,53 @@ Uint16 DcmSCU::checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ & /*eventReportRe void DcmSCU::notifySENDProgress(const unsigned long byteCount) { - DCMNET_TRACE("Bytes sent: " << byteCount); + DCMNET_TRACE("Bytes sent: " << byteCount); } - void DcmSCU::notifyRECEIVEProgress(const unsigned long byteCount) { - DCMNET_TRACE("Bytes received: " << byteCount); + DCMNET_TRACE("Bytes received: " << byteCount); } - /* ************************************************************************* */ /* Various helpers */ /* ************************************************************************* */ // Sends a DIMSE command and possibly also instance data to the configured peer DICOM application OFCondition DcmSCU::sendDIMSEMessage(const T_ASC_PresentationContextID presID, - T_DIMSE_Message *msg, - DcmDataset *dataObject, - DcmDataset **commandSet) -{ - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; - if (msg == NULL) - return DIMSE_NULLKEY; - - OFCondition cond; - /* call the corresponding DIMSE function to send the message */ - if (m_progressNotificationMode) - { - cond = DIMSE_sendMessageUsingMemoryData(m_assoc, presID, msg, NULL /*statusDetail*/, dataObject, - callbackSENDProgress, this /*callbackData*/, commandSet); - } else { - cond = DIMSE_sendMessageUsingMemoryData(m_assoc, presID, msg, NULL /*statusDetail*/, dataObject, - NULL /*callback*/, NULL /*callbackData*/, commandSet); - } + T_DIMSE_Message* msg, + DcmDataset* dataObject, + DcmDataset** commandSet) +{ + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; + if (msg == NULL) + return DIMSE_NULLKEY; + + OFCondition cond; + /* call the corresponding DIMSE function to send the message */ + if (m_progressNotificationMode) + { + cond = DIMSE_sendMessageUsingMemoryData(m_assoc, + presID, + msg, + NULL /*statusDetail*/, + dataObject, + callbackSENDProgress, + this /*callbackData*/, + commandSet); + } + else + { + cond = DIMSE_sendMessageUsingMemoryData(m_assoc, + presID, + msg, + NULL /*statusDetail*/, + dataObject, + NULL /*callback*/, + NULL /*callbackData*/, + commandSet); + } #if 0 // currently disabled because it is not (yet) needed @@ -2191,312 +2176,275 @@ OFCondition DcmSCU::sendDIMSEMessage(const T_ASC_PresentationContextID presID, } #endif - return cond; + return cond; } - // Receive DIMSE command (excluding dataset!) over the currently open association -OFCondition DcmSCU::receiveDIMSECommand(T_ASC_PresentationContextID *presID, - T_DIMSE_Message *msg, - DcmDataset **statusDetail, - DcmDataset **commandSet, +OFCondition DcmSCU::receiveDIMSECommand(T_ASC_PresentationContextID* presID, + T_DIMSE_Message* msg, + DcmDataset** statusDetail, + DcmDataset** commandSet, const Uint32 timeout) { - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - OFCondition cond; - if (timeout > 0) - { - /* call the corresponding DIMSE function to receive the command (use specified timeout)*/ - cond = DIMSE_receiveCommand(m_assoc, DIMSE_NONBLOCKING, timeout, presID, - msg, statusDetail, commandSet); - } else { - /* call the corresponding DIMSE function to receive the command (use default timeout) */ - cond = DIMSE_receiveCommand(m_assoc, m_blockMode, m_dimseTimeout, presID, - msg, statusDetail, commandSet); - } - return cond; + OFCondition cond; + if (timeout > 0) + { + /* call the corresponding DIMSE function to receive the command (use specified timeout)*/ + cond = DIMSE_receiveCommand(m_assoc, DIMSE_NONBLOCKING, timeout, presID, msg, statusDetail, commandSet); + } + else + { + /* call the corresponding DIMSE function to receive the command (use default timeout) */ + cond = DIMSE_receiveCommand(m_assoc, m_blockMode, m_dimseTimeout, presID, msg, statusDetail, commandSet); + } + return cond; } // Receives one dataset (of instance data) via network from another DICOM application -OFCondition DcmSCU::receiveDIMSEDataset(T_ASC_PresentationContextID *presID, - DcmDataset **dataObject) +OFCondition DcmSCU::receiveDIMSEDataset(T_ASC_PresentationContextID* presID, DcmDataset** dataObject) { - if (!isConnected()) - return DIMSE_ILLEGALASSOCIATION; + if (!isConnected()) + return DIMSE_ILLEGALASSOCIATION; - OFCondition cond; - /* call the corresponding DIMSE function to receive the dataset */ - if (m_progressNotificationMode) - { - cond = DIMSE_receiveDataSetInMemory(m_assoc, m_blockMode, m_dimseTimeout, presID, dataObject, - callbackRECEIVEProgress, this /*callbackData*/); - } else { - cond = DIMSE_receiveDataSetInMemory(m_assoc, m_blockMode, m_dimseTimeout, presID, dataObject, - NULL /*callback*/, NULL /*callbackData*/); - } + OFCondition cond; + /* call the corresponding DIMSE function to receive the dataset */ + if (m_progressNotificationMode) + { + cond = DIMSE_receiveDataSetInMemory( + m_assoc, m_blockMode, m_dimseTimeout, presID, dataObject, callbackRECEIVEProgress, this /*callbackData*/); + } + else + { + cond = DIMSE_receiveDataSetInMemory( + m_assoc, m_blockMode, m_dimseTimeout, presID, dataObject, NULL /*callback*/, NULL /*callbackData*/); + } - if (cond.good()) - { - DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); - } - else - { - OFString tempStr; - DCMNET_ERROR("Unable to receive dataset on presentation context " - << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); - } - return cond; + if (cond.good()) + { + DCMNET_DEBUG("Received dataset on presentation context " << OFstatic_cast(unsigned int, *presID)); + } + else + { + OFString tempStr; + DCMNET_ERROR("Unable to receive dataset on presentation context " + << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond)); + } + return cond; } - void DcmSCU::setMaxReceivePDULength(const Uint32 maxRecPDU) { - m_maxReceivePDULength = maxRecPDU; + m_maxReceivePDULength = maxRecPDU; } - void DcmSCU::setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode) { - m_blockMode = blockingMode; + m_blockMode = blockingMode; } - -void DcmSCU::setAETitle(const OFString &myAETtitle) +void DcmSCU::setAETitle(const OFString& myAETtitle) { - m_ourAETitle = myAETtitle; + m_ourAETitle = myAETtitle; } - -void DcmSCU::setPeerHostName(const OFString &peerHostName) +void DcmSCU::setPeerHostName(const OFString& peerHostName) { - m_peer = peerHostName; + m_peer = peerHostName; } - -void DcmSCU::setPeerAETitle(const OFString &peerAETitle) +void DcmSCU::setPeerAETitle(const OFString& peerAETitle) { - m_peerAETitle = peerAETitle; + m_peerAETitle = peerAETitle; } - void DcmSCU::setPeerPort(const Uint16 peerPort) { - m_peerPort = peerPort; + m_peerPort = peerPort; } - void DcmSCU::setDIMSETimeout(const Uint32 dimseTimeout) { - m_dimseTimeout = dimseTimeout; + m_dimseTimeout = dimseTimeout; } - void DcmSCU::setACSETimeout(const Uint32 acseTimeout) { - m_acseTimeout = acseTimeout; + m_acseTimeout = acseTimeout; } - void DcmSCU::setConnectionTimeout(const Sint32 connectionTimeout) { - dcmConnectionTimeout.set(connectionTimeout); + dcmConnectionTimeout.set(connectionTimeout); } - -void DcmSCU::setAssocConfigFileAndProfile(const OFString &filename, - const OFString &profile) +void DcmSCU::setAssocConfigFileAndProfile(const OFString& filename, const OFString& profile) { - m_assocConfigFilename = filename; - m_assocConfigProfile = profile; + m_assocConfigFilename = filename; + m_assocConfigProfile = profile; } - void DcmSCU::setStorageDir(const OFString& storeDir) { - m_storageDir = storeDir; + m_storageDir = storeDir; } - void DcmSCU::setStorageMode(const DcmStorageMode storageMode) { - m_storageMode = storageMode; + m_storageMode = storageMode; } - void DcmSCU::setVerbosePCMode(const OFBool mode) { - m_verbosePCMode = mode; + m_verbosePCMode = mode; } - void DcmSCU::setDatasetConversionMode(const OFBool mode) { - m_datasetConversionMode = mode; + m_datasetConversionMode = mode; } - void DcmSCU::setProgressNotificationMode(const OFBool mode) { - m_progressNotificationMode = mode; + m_progressNotificationMode = mode; } - /* Get methods */ OFBool DcmSCU::isConnected() const { - return (m_assoc != NULL) && (m_assoc->DULassociation != NULL); + return (m_assoc != NULL) && (m_assoc->DULassociation != NULL); } Uint32 DcmSCU::getMaxReceivePDULength() const { - return m_maxReceivePDULength; + return m_maxReceivePDULength; } - OFBool DcmSCU::getTLSEnabled() const { - return OFFalse; + return OFFalse; } - T_DIMSE_BlockingMode DcmSCU::getDIMSEBlockingMode() const { - return m_blockMode; + return m_blockMode; } - -const OFString &DcmSCU::getAETitle() const +const OFString& DcmSCU::getAETitle() const { - return m_ourAETitle; + return m_ourAETitle; } - -const OFString &DcmSCU::getPeerHostName() const +const OFString& DcmSCU::getPeerHostName() const { - return m_peer; + return m_peer; } - -const OFString &DcmSCU::getPeerAETitle() const +const OFString& DcmSCU::getPeerAETitle() const { - return m_peerAETitle; + return m_peerAETitle; } - Uint16 DcmSCU::getPeerPort() const { - return m_peerPort; + return m_peerPort; } - Uint32 DcmSCU::getDIMSETimeout() const { - return m_dimseTimeout; + return m_dimseTimeout; } - Uint32 DcmSCU::getACSETimeout() const { - return m_acseTimeout; + return m_acseTimeout; } - Sint32 DcmSCU::getConnectionTimeout() const { - return dcmConnectionTimeout.get(); + return dcmConnectionTimeout.get(); } - OFString DcmSCU::getStorageDir() const { - return m_storageDir; + return m_storageDir; } - DcmStorageMode DcmSCU::getStorageMode() const { - return m_storageMode; + return m_storageMode; } - OFBool DcmSCU::getVerbosePCMode() const { - return m_verbosePCMode; + return m_verbosePCMode; } - OFBool DcmSCU::getDatasetConversionMode() const { - return m_datasetConversionMode; + return m_datasetConversionMode; } - OFBool DcmSCU::getProgressNotificationMode() const { - return m_progressNotificationMode; + return m_progressNotificationMode; } - -OFCondition DcmSCU::getDatasetInfo(DcmDataset *dataset, - OFString &sopClassUID, - OFString &sopInstanceUID, - E_TransferSyntax &transferSyntax) +OFCondition DcmSCU::getDatasetInfo(DcmDataset* dataset, + OFString& sopClassUID, + OFString& sopInstanceUID, + E_TransferSyntax& transferSyntax) { - OFCondition status = EC_IllegalParameter; - sopClassUID.clear(); - sopInstanceUID.clear(); - transferSyntax = EXS_Unknown; - if (dataset != NULL) - { - // ignore returned condition codes (e.g. EC_TagNotFound) - dataset->findAndGetOFString(DCM_SOPClassUID, sopClassUID); - dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID); - transferSyntax = dataset->getOriginalXfer(); - // check return values for validity - if (sopClassUID.empty()) - status = NET_EC_InvalidSOPClassUID; - else if (sopInstanceUID.empty()) - status = NET_EC_InvalidSOPInstanceUID; - else if (transferSyntax == EXS_Unknown) - status = NET_EC_UnknownTransferSyntax; - else - status = EC_Normal; - } - return status; + OFCondition status = EC_IllegalParameter; + sopClassUID.clear(); + sopInstanceUID.clear(); + transferSyntax = EXS_Unknown; + if (dataset != NULL) + { + // ignore returned condition codes (e.g. EC_TagNotFound) + dataset->findAndGetOFString(DCM_SOPClassUID, sopClassUID); + dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID); + transferSyntax = dataset->getOriginalXfer(); + // check return values for validity + if (sopClassUID.empty()) + status = NET_EC_InvalidSOPClassUID; + else if (sopInstanceUID.empty()) + status = NET_EC_InvalidSOPInstanceUID; + else if (transferSyntax == EXS_Unknown) + status = NET_EC_UnknownTransferSyntax; + else + status = EC_Normal; + } + return status; } - /* ************************************************************************* */ /* Callback functions */ /* ************************************************************************* */ -void DcmSCU::callbackSENDProgress(void *callbackContext, - const unsigned long byteCount) +void DcmSCU::callbackSENDProgress(void* callbackContext, const unsigned long byteCount) { - if (callbackContext != NULL) - OFreinterpret_cast(DcmSCU *, callbackContext)->notifySENDProgress(byteCount); + if (callbackContext != NULL) + OFreinterpret_cast(DcmSCU*, callbackContext)->notifySENDProgress(byteCount); } - -void DcmSCU::callbackRECEIVEProgress(void *callbackContext, - const unsigned long byteCount) +void DcmSCU::callbackRECEIVEProgress(void* callbackContext, const unsigned long byteCount) { - if (callbackContext != NULL) - OFreinterpret_cast(DcmSCU *, callbackContext)->notifyRECEIVEProgress(byteCount); + if (callbackContext != NULL) + OFreinterpret_cast(DcmSCU*, callbackContext)->notifyRECEIVEProgress(byteCount); } - /* ************************************************************************* */ /* class RetrieveResponse */ /* ************************************************************************* */ void RetrieveResponse::print() { - DCMNET_INFO(" Number of Remaining Suboperations : " << m_numberOfRemainingSubops); - DCMNET_INFO(" Number of Completed Suboperations : " << m_numberOfCompletedSubops); - DCMNET_INFO(" Number of Failed Suboperations : " << m_numberOfFailedSubops); - DCMNET_INFO(" Number of Warning Suboperations : " << m_numberOfWarningSubops); + DCMNET_INFO(" Number of Remaining Suboperations : " << m_numberOfRemainingSubops); + DCMNET_INFO(" Number of Completed Suboperations : " << m_numberOfCompletedSubops); + DCMNET_INFO(" Number of Failed Suboperations : " << m_numberOfFailedSubops); + DCMNET_INFO(" Number of Warning Suboperations : " << m_numberOfWarningSubops); } diff --git a/dcmnet/tests/CMakeLists.txt b/dcmnet/tests/CMakeLists.txt index 2044aa1e..b8c0ab5a 100644 --- a/dcmnet/tests/CMakeLists.txt +++ b/dcmnet/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # declare executables -DCMTK_ADD_EXECUTABLE(dcmnet_tests tests tdump tpool tscuscp) +DCMTK_ADD_EXECUTABLE(dcmnet_tests tests tdump tdimse tpool tscuscp tscusession) # make sure executables are linked to the corresponding libraries DCMTK_TARGET_LINK_MODULES(dcmnet_tests dcmnet) diff --git a/dcmnet/tests/Makefile.dep b/dcmnet/tests/Makefile.dep index 5a521d91..172d63bf 100644 --- a/dcmnet/tests/Makefile.dep +++ b/dcmnet/tests/Makefile.dep @@ -247,12 +247,12 @@ tpool.o: tpool.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/scu.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/scu.h tscuscp.o: tscuscp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/oftest.h \ @@ -380,9 +380,143 @@ tscuscp.o: tscuscp.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ - ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/scpcfg.h \ - ../include/dcmtk/dcmnet/dcasccff.h ../include/dcmtk/dcmnet/dcasccfg.h \ - ../include/dcmtk/dcmnet/dccftsmp.h ../include/dcmtk/dcmnet/dccfuidh.h \ - ../include/dcmtk/dcmnet/dccfpcmp.h ../include/dcmtk/dcmnet/dccfrsmp.h \ - ../include/dcmtk/dcmnet/dccfenmp.h ../include/dcmtk/dcmnet/dccfprmp.h \ - ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/scu.h + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/scu.h +tscusession.o: tscusession.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmnet/scp.h ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ + ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dntypes.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/diutil.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/scu.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../../ofstd/include/dcmtk/ofstd/oftimer.h diff --git a/dcmnet/tests/Makefile.in b/dcmnet/tests/Makefile.in index c12b3af4..2d87c9cf 100644 --- a/dcmnet/tests/Makefile.in +++ b/dcmnet/tests/Makefile.in @@ -23,7 +23,7 @@ LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ LOCALLIBS = -ldcmnet -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(TCPWRAPPERLIBS) \ $(CHARCONVLIBS) $(MATHLIBS) -objs = tests.o tdump.o tpool.o tscuscp.o +objs = tests.o tdump.o tdimse.o tpool.o tscuscp.o tscusession.o progs = tests diff --git a/dcmnet/tests/tdimse.cc b/dcmnet/tests/tdimse.cc new file mode 100644 index 00000000..512f8877 --- /dev/null +++ b/dcmnet/tests/tdimse.cc @@ -0,0 +1,89 @@ +/* + * + * Copyright (C) 2020, J. Riesmeier, Oldenburg, Germany + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Joerg Riesmeier + * + * Purpose: test program for DIMSE Status Codes and Classes + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmnet/dimse.h" + + +OFTEST(dcmnet_dimseStatusClass) +{ + // success + OFCHECK( DICOM_SUCCESS_STATUS(0x0000)); + OFCHECK(!DICOM_SUCCESS_STATUS(0xabce)); + // failure + OFCHECK( DICOM_FAILURE_STATUS(0xa000)); + OFCHECK( DICOM_FAILURE_STATUS(0xa001)); + OFCHECK( DICOM_FAILURE_STATUS(0xabcd)); + OFCHECK(!DICOM_FAILURE_STATUS(0xb000)); + OFCHECK(!DICOM_FAILURE_STATUS(0xbeaf)); + OFCHECK( DICOM_FAILURE_STATUS(0xc000)); + OFCHECK( DICOM_FAILURE_STATUS(0xc0c0)); + OFCHECK( DICOM_FAILURE_STATUS(0xcfff)); + OFCHECK(!DICOM_FAILURE_STATUS(0xd000)); + OFCHECK(!DICOM_FAILURE_STATUS(0xd00f)); + OFCHECK( DICOM_FAILURE_STATUS(0x0100)); + OFCHECK(!DICOM_FAILURE_STATUS(0x0107)); + OFCHECK( DICOM_FAILURE_STATUS(0x0108)); + OFCHECK(!DICOM_FAILURE_STATUS(0x0116)); + OFCHECK( DICOM_FAILURE_STATUS(0x0117)); + OFCHECK( DICOM_FAILURE_STATUS(0x01ff)); + OFCHECK( DICOM_FAILURE_STATUS(0x0200)); + OFCHECK( DICOM_FAILURE_STATUS(0x0222)); + OFCHECK( DICOM_FAILURE_STATUS(0x02ff)); + OFCHECK(!DICOM_FAILURE_STATUS(0x0300)); + OFCHECK(!DICOM_FAILURE_STATUS(0x2200)); + // warning + OFCHECK(!DICOM_WARNING_STATUS(0x0000)); + OFCHECK( DICOM_WARNING_STATUS(0x0001)); + OFCHECK(!DICOM_WARNING_STATUS(0x0002)); + OFCHECK( DICOM_WARNING_STATUS(0x0107)); + OFCHECK(!DICOM_WARNING_STATUS(0x0108)); + OFCHECK( DICOM_WARNING_STATUS(0x0116)); + OFCHECK(!DICOM_WARNING_STATUS(0x0117)); + OFCHECK( DICOM_WARNING_STATUS(0xb000)); + OFCHECK( DICOM_WARNING_STATUS(0xb001)); + OFCHECK( DICOM_WARNING_STATUS(0xbfff)); + OFCHECK(!DICOM_WARNING_STATUS(0xc000)); + // cancel + OFCHECK( DICOM_CANCEL_STATUS (0xfe00)); + OFCHECK(!DICOM_CANCEL_STATUS (0xfe01)); + OFCHECK(!DICOM_CANCEL_STATUS (0xfefe)); + // pending + OFCHECK( DICOM_PENDING_STATUS(0xff00)); + OFCHECK( DICOM_PENDING_STATUS(0xff01)); + OFCHECK(!DICOM_PENDING_STATUS(0xff02)); + OFCHECK(!DICOM_PENDING_STATUS(0xffff)); + // any of the standard codes + OFCHECK( DICOM_STANDARD_STATUS(0x0000)); + OFCHECK( DICOM_STANDARD_STATUS(0x0001)); + OFCHECK( DICOM_STANDARD_STATUS(0x0111)); + OFCHECK( DICOM_STANDARD_STATUS(0x0222)); + OFCHECK(!DICOM_STANDARD_STATUS(0x0300)); + OFCHECK(!DICOM_STANDARD_STATUS(0x9999)); + OFCHECK( DICOM_STANDARD_STATUS(0xabcd)); + OFCHECK( DICOM_STANDARD_STATUS(0xbcde)); + OFCHECK( DICOM_STANDARD_STATUS(0xc0de)); + OFCHECK(!DICOM_STANDARD_STATUS(0xdead)); + OFCHECK(!DICOM_STANDARD_STATUS(0xffff)); +} diff --git a/dcmnet/tests/tdump.cc b/dcmnet/tests/tdump.cc index ed675f09..4e0dd0d3 100644 --- a/dcmnet/tests/tdump.cc +++ b/dcmnet/tests/tdump.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2009-2015, OFFIS e.V. + * Copyright (C) 2009-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -25,11 +25,19 @@ #include "dcmtk/ofstd/oftest.h" #include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcdict.h" #include "dcmtk/dcmnet/dimse.h" OFTEST(dcmnet_dimseDump_nullByte) { + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + const char expected[] = "===================== INCOMING DIMSE MESSAGE ====================\nMessage Type : C-ECHO RQ\nMessage ID : 42\nData Set : present\n-----------------------------------------------------------------(fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n(0000,1000) UI [1.2\0] # 4, 1 AffectedSOPInstanceUID\n(fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n======================= END DIMSE MESSAGE ======================="; OFString result; T_DIMSE_C_EchoRQ rq = { 42, "1.2.3\0", DIMSE_DATASET_PRESENT }; diff --git a/dcmnet/tests/tests.cc b/dcmnet/tests/tests.cc index a20e2f07..c84a701f 100644 --- a/dcmnet/tests/tests.cc +++ b/dcmnet/tests/tests.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2012-2017, OFFIS e.V. + * Copyright (C) 2012-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,6 +24,7 @@ #include "dcmtk/ofstd/oftest.h" OFTEST_REGISTER(dcmnet_dimseDump_nullByte); +OFTEST_REGISTER(dcmnet_dimseStatusClass); #ifdef WITH_THREADS OFTEST_REGISTER(dcmnet_scp_pool); @@ -36,6 +37,7 @@ OFTEST_REGISTER(dcmnet_scp_no_stop_wo_request_noblock); OFTEST_REGISTER(dcmnet_scp_no_stop_wo_request_block); OFTEST_REGISTER(dcmnet_scp_no_term_notify_without_association); OFTEST_REGISTER(dcmnet_scp_role_selection); +OFTEST_REGISTER(dcmnet_scu_session_handler); #endif // WITH_THREADS OFTEST_MAIN("dcmnet") diff --git a/dcmnet/tests/tscusession.cc b/dcmnet/tests/tscusession.cc new file mode 100644 index 00000000..7ae4ff53 --- /dev/null +++ b/dcmnet/tests/tscusession.cc @@ -0,0 +1,349 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * Open Connections GmbH + * Stau 33 + * D-26122 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Michael Onken + * + * Purpose: Test DcmSCU's C-FIND/GET/MOVE session handling + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef WITH_THREADS + +#define INCLUDE_CMATH +#include "dcmtk/dcmnet/scp.h" +#include "dcmtk/dcmnet/scu.h" +#include "dcmtk/ofstd/ofstdinc.h" +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/ofstd/oftimer.h" + +static Uint8 NUM_DIMSE_REQUESTS = 5; + +/** Method that ensures that the current thread is actually sleeping for the + * defined number of seconds (at least). + * @param sleep The number of seconds to sleep (at least) + */ +static void force_sleep(Uint32 sleep) +{ + OFTimer timer; + double elapsed = timer.getDiff(); + while (elapsed < (double)sleep) + { + // Use ceiling since otherwise we could wait too short + OFStandard::sleep(OFstatic_cast(unsigned int, ceil(sleep - elapsed))); + elapsed = timer.getDiff(); + } +} + +/** SCP derived from DcmSCP that has simple handlers for MOVE, GET and FIND + * and allows stopping after one association. + */ +struct SessionSCP : public DcmSCP, OFThread +{ + + /** Constructor + */ + SessionSCP() + : DcmSCP() + { + } + + /** Overwrite method from DcmSCP in order to stop after one association. + * @return Returns OFTrue (stop after first association) + */ + virtual OFBool stopAfterCurrentAssociation() + { + return OFTrue; + } + + /** Overwrite DcmSCP method to enable handling of C-FIND and C-MOVE messages (TODO: C-GET) + * @param incomingMsg Incoming DIMSE message + * @param presInfo Presentation Context information + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition handleIncomingCommand(T_DIMSE_Message* incomingMsg, const DcmPresentationContextInfo& presInfo) + { + OFCondition result; + DcmDataset* dset = NULL; + if (incomingMsg->CommandField == DIMSE_C_FIND_RQ) + { + // Call our custom FIND handler + result = handleFIND(incomingMsg->msg.CFindRQ, presInfo.presentationContextID, dset); + } + else if (incomingMsg->CommandField == DIMSE_C_MOVE_RQ) + { + // Call our custom MOVE handler + OFString dest = incomingMsg->msg.CMoveRQ.MoveDestination; + result = handleMOVE(incomingMsg->msg.CMoveRQ, presInfo.presentationContextID, dset, dest); + } + else + result = DcmSCP::handleIncomingCommand(incomingMsg, presInfo); + + delete dset; + return result; + } + + /** Overwrite DcmSCP method to to add specific C-MOVE handler. Sends NUM_DIMSE_REQUESTS + * DIMSE responses back, all in status PENDING, last in status SUCCESS. + * @param reqMessage Incoming DIMSE message + * @param presID Presentation Context ID + * @param reqDataset Request dataset + * @param moveDest Move Destination AE Title + * @return EC_Normal if successful, error otherwise + */ + OFCondition handleMOVE(T_DIMSE_C_MoveRQ& reqMessage, + const T_ASC_PresentationContextID presID, + DcmDataset*& reqDataset, + OFString& moveDest) + { + OFCondition result = DcmSCP::receiveMOVERequest(reqMessage, presID, reqDataset, moveDest); + if (result.good()) + { + OFString sop_class, ts; + OFunique_ptr rsp(new DcmDataset); + *rsp = *reqDataset; + DcmSCP::findPresentationContext(presID, sop_class, ts); + Uint16 status = STATUS_MOVE_Pending_SubOperationsAreContinuing; + // Send back configured number of responses, all but last with status PENDING (last: SUCCESS). + // All but the last one will return a copy of the request dataset (random choice for this test; + // last response will not have a dataset. + for (Uint8 n = 1; n <= NUM_DIMSE_REQUESTS; n++) + { + if (n == NUM_DIMSE_REQUESTS) + { + rsp.reset(NULL); + status = STATUS_Success; + } + result = DcmSCP::sendMOVEResponse( + presID, reqMessage.MessageID, sop_class, rsp.get(), status, NULL, NUM_DIMSE_REQUESTS - n, n, 0, 0); + } + } + return result; + } + + /** Overwrite DcmSCP method to to add specific C-FIND handler. Sends NUM_DIMSE_REQUESTS + * DIMSE responses back, all in status PENDING, last in status SUCCESS. + * @param reqMessage Incoming DIMSE message + * @param presID Presentation Context ID + * @param reqDataset Request dataset + * @return EC_Normal if successful, error otherwise + */ + OFCondition + handleFIND(T_DIMSE_C_FindRQ& reqMessage, const T_ASC_PresentationContextID presID, DcmDataset*& reqDataset) + { + OFCondition result = DcmSCP::receiveFINDRequest(reqMessage, presID, reqDataset); + if (result.good()) + { + OFString sop_class, ts; + OFunique_ptr rsp(new DcmDataset); + *rsp = *reqDataset; + DcmSCP::findPresentationContext(presID, sop_class, ts); + Uint16 status = STATUS_FIND_Pending_MatchesAreContinuing; + // Send back configured number of responses, all but last with status PENDING (last: SUCCESS). + // All but the last one will return a copy of the request dataset (random choice for this test; + // last response will not have a dataset. + for (Uint8 n = 1; n <= NUM_DIMSE_REQUESTS; n++) + { + if (n == NUM_DIMSE_REQUESTS) + { + rsp.reset(NULL); + status = STATUS_Success; + } + result = DcmSCP::sendFINDResponse(presID, reqMessage.MessageID, sop_class, rsp.get(), status, NULL); + } + } + return result; + } + + /** Method called by OFThread to start SCP operation. Starts listen() loop of DcmSCP. + */ + virtual void run() + { + listen(); + } +}; + +/** Class derived from DcmSCU that has support for C-FIND/MOVE and GET-related + * SOP Classes. Also it has handlers for those DIMSE messages call the original + * handlers from DcmSCU and simply count how often they are called. + * The goal is to exercise the internal default response handing built into + * DcmSCU for handling C-FIND/MOVE and GET-related "sessions". + */ +struct SessionSCU : public DcmSCU +{ + /** Constructor + */ + SessionSCU() + : m_session_counter(0) + { + OFList ts; + ts.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCHECK(addPresentationContext(UID_FINDPatientRootQueryRetrieveInformationModel, ts).good()); + OFCHECK(addPresentationContext(UID_MOVEPatientRootQueryRetrieveInformationModel, ts).good()); + OFCHECK(addPresentationContext(UID_GETPatientRootQueryRetrieveInformationModel, ts).good()); + } + + /** Overwrites method from DcmSCU. + * Handles incoming C-GET response. Just counts number of calls and then forwards + * handling to default DcmSCU handler. + * @param presID Presentation Context ID + * @param response The C-GET response received + * @param continueCGETSession Will receive information whether it should be waited + * for further C-GET responses. + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition handleCGETResponse(const T_ASC_PresentationContextID presID, + RetrieveResponse* response, + OFBool& continueCGETSession) + { + m_session_counter++; + return DcmSCU::handleCGETResponse(presID, response, continueCGETSession); + } + + /** Overwrites method from DcmSCU. + * Handles incoming C-MOVE response. Just counts number of calls and then forwards + * handling to default DcmSCU handler. + * @param presID Presentation Context ID + * @param response The C-MOVE response received + * @param waitForNextResponse Will receive information whether it should be waited + * for further C-MOVE responses. + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition handleMOVEResponse(const T_ASC_PresentationContextID presID, + RetrieveResponse* response, + OFBool& waitForNextResponse) + { + m_session_counter++; + return DcmSCU::handleMOVEResponse(presID, response, waitForNextResponse); + } + + /** Overwrites method from DcmSCU. + * Handles incoming C-FIND response. Just counts number of calls and then forwards + * handling to default DcmSCU handler. + * @param presID Presentation Context ID + * @param response The C-FIND response received + * @param waitForNextResponse Will receive information whether it should be waited + * for further C-FIND responses. + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition + handleFINDResponse(const T_ASC_PresentationContextID presID, QRResponse* response, OFBool& waitForNextResponse) + { + m_session_counter++; + OFCondition result = DcmSCU::handleFINDResponse(presID, response, waitForNextResponse); + return result; + } + + /** Virtual destructor */ + virtual ~SessionSCU() + { + } + + /** Counter for number of DIMSE messages handled + */ + size_t m_session_counter; +}; + +// -------------- End of class SessionSCP ------------------------- + +/** Manually configure Verification SOP class on server + * @param cfg The SCP configuration to modify + * @param sop_class SOP class to be supported + * @param roleOfRequestor role to be negotiated + */ +void configure_scp_for_sop_class(DcmSCPConfig& cfg, + const OFString& sop_class, + T_ASC_SC_ROLE roleOfRequestor = ASC_SC_ROLE_DEFAULT) +{ + cfg.setPort(11112); + OFList xfers; + xfers.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCHECK(cfg.addPresentationContext(sop_class, xfers, roleOfRequestor).good()); +} + +/** Initiate SCU and perform session with SCP using given SOP class. + * @param called_ae_title The Called AE Title to be used + * @param sop_class The SOP class to negotiate + */ +void scu_session(const OFString& called_ae_title, const OFString& sop_class) +{ + // Make sure server is up + force_sleep(1); + // Basic configuration + SessionSCU scu; + scu.setAETitle("TEST_SCU"); + scu.setPeerAETitle(called_ae_title); + scu.setPeerHostName("localhost"); + scu.setPeerPort(11112); + OFList xfers; + xfers.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCondition result = scu.addPresentationContext(sop_class, xfers); + OFCHECK(result.good()); + result = scu.initNetwork(); + OFCHECK(result.good()); + + // Start connection + result = scu.negotiateAssociation(); + OFCHECK(result.good()); + + // Build simple query + DcmDataset query; + query.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "PATIENT"); + query.putAndInsertOFStringArray(DCM_PatientID, "0815"); + // Send FIND, GET (TODO), or MOVE + if (sop_class == UID_FINDPatientRootQueryRetrieveInformationModel) + { + result = scu.sendFINDRequest(1, &query, NULL); + } + else if (sop_class == UID_MOVEPatientRootQueryRetrieveInformationModel) + { + result = scu.sendMOVERequest(3, "TEST_SCU", &query, NULL); + } + // Check whether session worked by comparing response count + OFCHECK(scu.m_session_counter == NUM_DIMSE_REQUESTS); + OFCHECK(result.good()); + // Release association + result = scu.releaseAssociation(); + OFCHECK(result.good()); + return; +} + +// Test case to check SCU session handling for C-FIND, C-MOVE and C-GET +OFTEST_FLAGS(dcmnet_scu_session_handler, EF_Slow) +{ + // Configure SCP and start it. + SessionSCP scp; + DcmSCPConfig& config = scp.getConfig(); + configure_scp_for_sop_class(config, UID_FINDPatientRootQueryRetrieveInformationModel); + configure_scp_for_sop_class(config, UID_GETPatientRootQueryRetrieveInformationModel); + configure_scp_for_sop_class(config, UID_MOVEPatientRootQueryRetrieveInformationModel); + config.setConnectionBlockingMode(DUL_BLOCK); + scp.start(); + + // Send FIND, and wait to be sure SCP has time to exit + scu_session("FIND_SESSION", UID_FINDPatientRootQueryRetrieveInformationModel); + force_sleep(1); + scp.join(); + + // Send MOVE, and wait to be sure SCP has time to exit + scp.start(); + scu_session("MOVE_SESSION", UID_MOVEPatientRootQueryRetrieveInformationModel); + force_sleep(1); + scp.join(); + + // TODO: Test C-GET +} + +#endif // WITH_THREADS diff --git a/dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h b/dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h index 728f39fe..725e5b6e 100644 --- a/dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h +++ b/dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2018, Open Connections GmbH + * Copyright (C) 2018-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -64,7 +64,7 @@ public: private: - // Make sure the Parametric Map object (and no one else) can use the constructor below. + /// Make sure the Parametric Map object (and no one else) can use the constructor below. friend class DPMParametricMapIOD; /** Create Frames object in DPMParametricMapIOD (see friend declaration above) diff --git a/dcmpmap/libsrc/Makefile.dep b/dcmpmap/libsrc/Makefile.dep index e945cfc1..42bdd71d 100644 --- a/dcmpmap/libsrc/Makefile.dep +++ b/dcmpmap/libsrc/Makefile.dep @@ -50,7 +50,8 @@ dpmmodparametricmapimage.o: dpmmodparametricmapimage.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ @@ -58,17 +59,15 @@ dpmmodparametricmapimage.o: dpmmodparametricmapimage.cc \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmpmap/dpmmodparametricmapimage.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmpmap/dpmdef.h @@ -124,7 +123,8 @@ dpmmodparametricmapseries.o: dpmmodparametricmapseries.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ @@ -132,17 +132,15 @@ dpmmodparametricmapseries.o: dpmmodparametricmapseries.cc \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmpmap/dpmmodparametricmapseries.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmpmap/dpmdef.h \ @@ -200,7 +198,9 @@ dpmmodparametricmapseries.o: dpmmodparametricmapseries.cc \ dpmparametricmapbase.o: dpmparametricmapbase.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ @@ -208,14 +208,13 @@ dpmparametricmapbase.o: dpmparametricmapbase.cc \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -241,29 +240,27 @@ dpmparametricmapbase.o: dpmparametricmapbase.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmpmap/dpmtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ @@ -324,10 +321,10 @@ dpmparametricmapbase.o: dpmparametricmapbase.cc \ ../include/dcmtk/dcmpmap/dpmdef.h \ ../include/dcmtk/dcmpmap/dpmparametricmapbase.h \ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ ../../dcmfg/include/dcmtk/dcmfg/fg.h \ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ ../../dcmfg/include/dcmtk/dcmfg/fgderimg.h \ ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ ../../dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h \ @@ -340,29 +337,29 @@ dpmparametricmapbase.o: dpmparametricmapbase.cc \ ../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ - ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ - ../../ofstd/include/dcmtk/ofstd/diag/push.def \ - ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ - ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ - ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ @@ -376,22 +373,18 @@ dpmparametricmapiod.o: dpmparametricmapiod.cc \ ../include/dcmtk/dcmpmap/dpmparametricmapiod.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../../ofstd/include/dcmtk/ofstd/ofmem.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ @@ -403,10 +396,14 @@ dpmparametricmapiod.o: dpmparametricmapiod.cc \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -431,14 +428,13 @@ dpmparametricmapiod.o: dpmparametricmapiod.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../include/dcmtk/dcmpmap/dpmparametricmapbase.h \ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -495,10 +491,10 @@ dpmparametricmapiod.o: dpmparametricmapiod.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ ../../dcmfg/include/dcmtk/dcmfg/fg.h \ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ ../../dcmfg/include/dcmtk/dcmfg/fgderimg.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ @@ -512,28 +508,28 @@ dpmparametricmapiod.o: dpmparametricmapiod.cc \ ../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ ../../ofstd/include/dcmtk/ofstd/diag/push.def \ ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ - ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ - ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ - ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ @@ -665,6 +661,5 @@ dpmtypes.o: dpmtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmpmap/dpmdef.h diff --git a/dcmpmap/libsrc/dpmparametricmapiod.cc b/dcmpmap/libsrc/dpmparametricmapiod.cc index 18feaf66..1b5e0590 100644 --- a/dcmpmap/libsrc/dpmparametricmapiod.cc +++ b/dcmpmap/libsrc/dpmparametricmapiod.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -367,34 +367,6 @@ private: }; -template<> -Uint8* DPMParametricMapIOD::WriteVisitor::DcmElementOf >::getData(const size_t size) -{ - if (m_pElement) - if (m_pElement->setVR(EVR_OB).good()) - { - Uint8* result; - if (m_pElement->createUint8Array(OFstatic_cast(Uint32, size), result).good()) - return result; - } - return OFnullptr; -} - - -template<> -Sint8* DPMParametricMapIOD::WriteVisitor::DcmElementOf >::getData(const size_t size) -{ - if (m_pElement) - if (m_pElement->setVR(EVR_OB).good()) - { - Uint8* result; - if (m_pElement->createUint8Array(OFstatic_cast(Uint32, size), result).good()) - return OFreinterpret_cast(Sint8*, result); - } - return OFnullptr; -} - - template<> Uint16* DPMParametricMapIOD::WriteVisitor::DcmElementOf >::getData(const size_t size /* num total pixels */) { diff --git a/dcmpstat/apps/dcmprscu.cc b/dcmpstat/apps/dcmprscu.cc index 399af7ae..15644d25 100644 --- a/dcmpstat/apps/dcmprscu.cc +++ b/dcmpstat/apps/dcmprscu.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2019, OFFIS e.V. + * Copyright (C) 1999-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -543,11 +543,11 @@ static OFCondition updateJobList( const char *spoolFolder = dvi.getSpoolFolder(); #ifdef HAVE_WINDOWS_H - WIN32_FIND_DATA stWin32FindData; + WIN32_FIND_DATAA stWin32FindData; OFString currentdir = spoolFolder; currentdir += "\\*"; - HANDLE hFile = FindFirstFile(currentdir.c_str(), &stWin32FindData); + HANDLE hFile = FindFirstFileA(currentdir.c_str(), &stWin32FindData); int ret = (hFile != INVALID_HANDLE_VALUE); while (ret) { @@ -595,7 +595,7 @@ static OFCondition updateJobList( } #ifdef HAVE_WINDOWS_H - ret = FindNextFile(hFile, &stWin32FindData); + ret = FindNextFileA(hFile, &stWin32FindData); } /* while */ if(hFile != INVALID_HANDLE_VALUE) { @@ -1067,7 +1067,7 @@ int main(int argc, char *argv[]) OFStandard::sleep((unsigned int)opt_sleep); if (EC_Normal != updateJobList(jobList, dvi, terminateFlag, jobNamePrefix.c_str())) { - OFLOG_FATAL(dcmprscuLogger, "spooler: non recoverable error occured, terminating"); + OFLOG_FATAL(dcmprscuLogger, "spooler: non recoverable error occurred, terminating"); return 10; } // static OFCondition updateJobList(jobList, dvi, terminateFlag, jobNamePrefix.c_str()); diff --git a/dcmpstat/apps/dcmpsprt.cc b/dcmpstat/apps/dcmpsprt.cc index c7273f24..574f7603 100644 --- a/dcmpstat/apps/dcmpsprt.cc +++ b/dcmpstat/apps/dcmpsprt.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1999-2019, OFFIS e.V. + * Copyright (C) 1999-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -80,9 +80,12 @@ static int addOverlay(const char *filename, for (unsigned long xs = 0; xs < xsize; xs++) { while (input.get(c) && !isdigit(OFstatic_cast(unsigned char, c))); // skip non-numeric chars - input.putback(c); - input >> value; - if (value) + if (!isdigit(OFstatic_cast(unsigned char, c))) + { + OFLOG_ERROR(dcmpsprtLogger, "syntax error in PBM file '" << filename << "'"); + return 0; + } + if (c != '0') *p = gray; p++; } @@ -90,7 +93,7 @@ static int addOverlay(const char *filename, } return 1; } else - OFLOG_ERROR(dcmpsprtLogger, "invalid position for overlay PBM file '" << filename); + OFLOG_ERROR(dcmpsprtLogger, "invalid position for overlay PBM file '" << filename << "'"); } else OFLOG_ERROR(dcmpsprtLogger, "overlay PBM file '" << filename << "' has no magic number P1"); } else @@ -445,7 +448,7 @@ int main(int argc, char *argv[]) /* dump printer characteristics if requested */ const char *currentPrinter = dvi.getCurrentPrinter(); - if ((opt_img_request_size) && (!dvi.getTargetPrinterSupportsRequestedImageSize(opt_printerID))) + if ((opt_img_request_size) && (!dvi.getTargetPrinterSupportsRequestedImageSize(currentPrinter))) OFLOG_WARN(dcmpsprtLogger, "printer does not support requested image size"); if (EC_Normal != dvi.getPrintHandler().setImageDisplayFormat(opt_columns, opt_rows)) @@ -645,7 +648,7 @@ int main(int argc, char *argv[]) { // no need to do this manually if we are spooling - spoolPrintJob() will do this anyway. OFLOG_WARN(dcmpsprtLogger, "writing DICOM stored print object to database."); - if (EC_Normal != dvi.saveStoredPrint(dvi.getTargetPrinterSupportsRequestedImageSize(opt_printerID))) + if (EC_Normal != dvi.saveStoredPrint(dvi.getTargetPrinterSupportsRequestedImageSize(currentPrinter))) { OFLOG_ERROR(dcmpsprtLogger, "error during creation of DICOM stored print object"); } diff --git a/dcmpstat/apps/dcmpsrcv.cc b/dcmpstat/apps/dcmpsrcv.cc index 2d108c88..0a578c5e 100644 --- a/dcmpstat/apps/dcmpsrcv.cc +++ b/dcmpstat/apps/dcmpsrcv.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1999-2019, OFFIS e.V. + * Copyright (C) 1999-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -547,7 +547,7 @@ static OFCondition storeSCP( dcmtk_flock(lockfd, LOCK_EX); #endif - /* we must still retrieve the data set even if some error has occured */ + /* we must still retrieve the data set even if some error has occurred */ StoreContext context(dbhandle, status, imageFileName, &dcmff, opt_correctUIDPadding); if (opt_bitpreserving) @@ -1315,8 +1315,8 @@ int main(int argc, char *argv[]) dropAssociation(&assoc); } else if (pid > 0) { - /* parent process */ - assoc = NULL; + /* we're the parent process, close accepted socket and continue */ + dropAssociation(&assoc); } else { /* child process */ @@ -1349,15 +1349,15 @@ int main(int argc, char *argv[]) // initialize startup info const char *receiver_application = dvi.getReceiverName(); PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; sprintf(commandline, "%s %s %s", receiver_application, opt_cfgName, opt_cfgID); #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { #ifdef WITH_OPENSSL diff --git a/dcmpstat/include/dcmtk/dcmpstat/dvpstx.h b/dcmpstat/include/dcmtk/dcmpstat/dvpstx.h index b3e3a0c2..bdf223c7 100644 --- a/dcmpstat/include/dcmtk/dcmpstat/dvpstx.h +++ b/dcmpstat/include/dcmtk/dcmpstat/dvpstx.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2012, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -92,9 +92,9 @@ public: /** sets bounding box for this text object. * @param TLHC_x bounding box top-lefthand corner X value - * @param TLHC_x bounding box top-lefthand corner Y value + * @param TLHC_y bounding box top-lefthand corner Y value * @param BRHC_x bounding box bottom-righthand corner X value - * @param BRHC_x bounding box bottom-righthand corner Y value + * @param BRHC_y bounding box bottom-righthand corner Y value * @param unit bounding box annotation units (pixel/display) * @param justification bounding box horizontal justification (left/right/center) * @return EC_Normal if successful, an error code otherwise. diff --git a/dcmpstat/libsrc/Makefile.dep b/dcmpstat/libsrc/Makefile.dep index 8fed5dd9..ef66ce2f 100644 --- a/dcmpstat/libsrc/Makefile.dep +++ b/dcmpstat/libsrc/Makefile.dep @@ -306,6 +306,7 @@ dviface.o: dviface.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmsign/include/dcmtk/dcmsign/sitypes.h \ ../../dcmsign/include/dcmtk/dcmsign/sidefine.h \ ../../dcmsign/include/dcmtk/dcmsign/dcsignat.h \ + ../../dcmsign/include/dcmtk/dcmsign/sipurpos.h \ ../../dcmsr/include/dcmtk/dcmsr/dsrdoc.h \ ../../dcmsr/include/dcmtk/dcmsr/dsrdoctr.h \ ../../dcmsr/include/dcmtk/dcmsr/dsrdocst.h \ @@ -4781,6 +4782,7 @@ dvsighdl.o: dvsighdl.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmsign/include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ diff --git a/dcmpstat/libsrc/dviface.cc b/dcmpstat/libsrc/dviface.cc index 43c1bf5d..d5f45226 100644 --- a/dcmpstat/libsrc/dviface.cc +++ b/dcmpstat/libsrc/dviface.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2019, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -2236,7 +2236,7 @@ OFCondition DVInterface::sendIOD(const char * targetID, // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; @@ -2246,9 +2246,9 @@ OFCondition DVInterface::sendIOD(const char * targetID, studyUID, seriesUID); else sprintf(commandline, "%s %s %s %s", sender_application, configPath.c_str(), targetID, studyUID); #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { return EC_Normal; @@ -2298,15 +2298,15 @@ OFCondition DVInterface::startReceiver() // Windows version - call CreateProcess() // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; sprintf(commandline, "%s %s %s", receiver_application, configPath.c_str(), getTargetID(i, DVPSE_receiver)); #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { // continue loop @@ -2353,15 +2353,15 @@ OFCondition DVInterface::terminateReceiver() // Windows version - call CreateProcess() // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; sprintf(commandline, "%s %s %s", receiver_application, configPath.c_str(), "--terminate"); #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { // continue loop @@ -2426,7 +2426,7 @@ OFCondition DVInterface::startQueryRetrieveServer() // Windows version - call CreateProcess() // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; @@ -2442,9 +2442,9 @@ OFCondition DVInterface::startQueryRetrieveServer() } #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { return EC_Normal; @@ -2972,6 +2972,7 @@ OFCondition DVInterface::saveStoredPrint( if (prependDateTime) { OFDateTime::getCurrentDateTime().getISOFormattedDateTime(text, OFFalse /*showSeconds*/); + text += " "; } if (prependPrinterName) { @@ -3387,7 +3388,7 @@ OFCondition DVInterface::startPrintSpooler() const char *printer = NULL; unsigned long sleepingTime = getSpoolerSleep(); if (sleepingTime==0) sleepingTime=1; // default - char sleepStr[20]; + char sleepStr[30]; sprintf(sleepStr, "%lu", sleepingTime); OFBool detailedLog = getDetailedLog(); @@ -3432,7 +3433,7 @@ OFCondition DVInterface::startPrintSpooler() // Windows version - call CreateProcess() // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; @@ -3445,9 +3446,9 @@ OFCondition DVInterface::startPrintSpooler() printJobIdentifier.c_str(), printer, configPath.c_str(), sleepStr); } #ifdef DEBUG - if (0 == CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (0 == CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (0 == CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (0 == CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { DCMPSTAT_ERROR("Unable to execute '" << spooler_application << "'"); @@ -3567,7 +3568,7 @@ OFCondition DVInterface::startPrintServer() // Windows version - call CreateProcess() // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; @@ -3578,9 +3579,9 @@ OFCondition DVInterface::startPrintServer() sprintf(commandline, "%s --logfile --printer %s --config %s", application, printer, configPath.c_str()); } #ifdef DEBUG - if (0 == CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (0 == CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (0 == CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (0 == CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { DCMPSTAT_ERROR("Unable to execute '" << application << "'"); @@ -3830,7 +3831,7 @@ OFCondition DVInterface::printSCUcreateBasicFilmSession(DVPSPrintMessageHandler& OFCondition result = EC_Normal; DcmDataset dset; DcmElement *delem = NULL; - char buf[20]; + char buf[30]; if ((EC_Normal==result)&&(printerMediumType.size() > 0)) { @@ -3922,15 +3923,15 @@ OFCondition DVInterface::startExternalApplication(const char *application, const // initialize startup info PROCESS_INFORMATION procinfo; - STARTUPINFO sinfo; + STARTUPINFOA sinfo; OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); char commandline[4096]; sprintf(commandline, "%s %s", application, filename); #ifdef DEBUG - if (CreateProcess(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo)) #else - if (CreateProcess(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) + if (CreateProcessA(NULL, commandline, NULL, NULL, 0, DETACHED_PROCESS, NULL, NULL, &sinfo, &procinfo)) #endif { return EC_Normal; diff --git a/dcmpstat/libsrc/dvpscu.cc b/dcmpstat/libsrc/dvpscu.cc index f5efccf6..be3c81fe 100644 --- a/dcmpstat/libsrc/dvpscu.cc +++ b/dcmpstat/libsrc/dvpscu.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2017, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -209,6 +209,7 @@ OFCondition DVPSCurve::read(DcmItem &dset, Uint8 group) case EVR_OB: case EVR_OW: case EVR_ox: + case EVR_px: case EVR_US: if (EC_Normal == d_curveData->getUint8Array(pui8)) diff --git a/dcmpstat/libsrc/dvsighdl.cc b/dcmpstat/libsrc/dvsighdl.cc index a64b8187..99918e77 100644 --- a/dcmpstat/libsrc/dvsighdl.cc +++ b/dcmpstat/libsrc/dvsighdl.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2010, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -151,7 +151,7 @@ void DVSignatureHandler::printSignatureItemPosition(DcmStack& stack, STD_NAMESPA unsigned long sqCard=0; const char *tagname = NULL; unsigned long m=0; - char buf[20]; + char buf[30]; OFBool printed = OFFalse; if (stack.card() > 2) @@ -333,6 +333,7 @@ void DVSignatureHandler::updateDigitalSignatureInformation(DcmItem& /*dataset*/, cert->getCertValidityNotAfter(aString); os << aString.c_str() << htmlEndl << htmlLine4 << "Public key" << htmlNext; + const char *ecname = NULL; switch (cert->getKeyType()) { case EKT_RSA: @@ -341,6 +342,17 @@ void DVSignatureHandler::updateDigitalSignatureInformation(DcmItem& /*dataset*/, case EKT_DSA: os << "DSA, " << cert->getCertKeyBits() << " bits" << htmlEndl; break; + case EKT_EC: + ecname = cert->getCertCurveName(); + if (ecname) + { + os << "EC, curve " << ecname << ", " << cert->getCertKeyBits() << " bits"; + } + else + { + os << "EC, " << cert->getCertKeyBits() << " bits"; + } + break; case EKT_DH: os << "DH, " << cert->getCertKeyBits() << " bits" << htmlEndl; break; diff --git a/dcmqrdb/docs/dcmqrscp.man b/dcmqrdb/docs/dcmqrscp.man index b932a235..620793da 100644 --- a/dcmqrdb/docs/dcmqrscp.man +++ b/dcmqrdb/docs/dcmqrscp.man @@ -761,6 +761,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -815,6 +821,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -854,6 +861,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -873,6 +882,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -1077,6 +1093,6 @@ It is an error if no data dictionary can be loaded. \section dcmqrscp_copyright COPYRIGHT -Copyright (C) 1993-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1993-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmqrdb/etc/dcmqrprf.cfg b/dcmqrdb/etc/dcmqrprf.cfg index 881db973..dcafed60 100644 --- a/dcmqrdb/etc/dcmqrprf.cfg +++ b/dcmqrdb/etc/dcmqrprf.cfg @@ -1,5 +1,5 @@ # -# Copyright (C) 2017-2019, OFFIS e.V. +# Copyright (C) 2017-2020, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by @@ -231,14 +231,21 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # # - AcquisitionContextSRStorage # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage # - BreastProjectionXRayImageStorageForPresentation # - BreastProjectionXRayImageStorageForProcessing +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage # - CompositingPlanarMPRVolumetricPresentationStateStorage # - ContentAssessmentResultsStorage # - CTDefinedProcedureProtocolStorage # - CTPerformedProcedureProtocolStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage # - ExtensibleSRStorage # - GrayscalePlanarMPRVolumetricPresentationStateStorage @@ -246,6 +253,7 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # - LegacyConvertedEnhancedCTImageStorage # - LegacyConvertedEnhancedMRImageStorage # - LegacyConvertedEnhancedPETImageStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -254,12 +262,20 @@ PresentationContext128 = DRAFT_WaveformStorage\UncompressedOrZlib # - PerformedImagingAgentAdministrationSRStorage # - PlannedImagingAgentAdministrationSRStorage # - RadiopharmaceuticalRadiationDoseSRStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTBrachyApplicationSetupDeliveryInstructionStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage # - SimplifiedAdultEchoSRStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - TractographyResultsStorage # - VolumeRenderingVolumetricPresentationStateStorage # - WideFieldOphthalmicPhotographyStereographicProjectionImageStorage @@ -423,9 +439,17 @@ PresentationContext128 = XRayRadiationDoseSRStorage\UncompressedOrZlib # the following SOP classes are missing in the above list: # # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -433,10 +457,18 @@ PresentationContext128 = XRayRadiationDoseSRStorage\UncompressedOrZlib # - PerformedImagingAgentAdministrationSRStorage # - PlannedImagingAgentAdministrationSRStorage # - ProtocolApprovalStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - VolumeRenderingVolumetricPresentationStateStorage # # - RETIRED_HardcopyColorImageStorage @@ -623,9 +655,11 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - AutorefractionMeasurementsStorage # - BasicStructuredDisplayStorage # - BlendingSoftcopyPresentationStateStorage +# - BodyPositionWaveformStorage # - BreastProjectionXRayImageStorageForPresentation # - BreastProjectionXRayImageStorageForProcessing # - BreastTomosynthesisImageStorage +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - CompositingPlanarMPRVolumetricPresentationStateStorage # - Comprehensive3DSRStorage @@ -634,7 +668,12 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - CTDefinedProcedureProtocolStorage # - CTPerformedProcedureProtocolStorage # - DeformableSpatialRegistrationStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage # - EncapsulatedCDAStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage # - EnhancedMRColorImageStorage # - EnhancedPETImageStorage @@ -655,6 +694,7 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - LegacyConvertedEnhancedPETImageStorage # - LensometryMeasurementsStorage # - MacularGridThicknessAndVolumeReportStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicAxialMeasurementsStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage @@ -670,21 +710,29 @@ PresentationContext128 = VideoPhotographicImageStorage\MPEG2 # - RadiopharmaceuticalRadiationDoseSRStorage # - RealWorldValueMappingStorage # - RespiratoryWaveformStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTBeamsDeliveryInstructionStorage # - RTBrachyApplicationSetupDeliveryInstructionStorage # - RTIonBeamsTreatmentRecordStorage # - RTIonPlanStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage # - SimplifiedAdultEchoSRStorage +# - SleepElectroencephalogramWaveformStorage # - SpectaclePrescriptionReportStorage # - SubjectiveRefractionMeasurementsStorage # - SurfaceScanMeshStorage # - SurfaceScanPointCloudStorage # - SurfaceSegmentationStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - TractographyResultsStorage # - VisualAcuityMeasurementsStorage # - VLWholeSlideMicroscopyImageStorage @@ -863,14 +911,21 @@ Role127 = DRAFT_WaveformStorage\BOTH # # - AcquisitionContextSRStorage # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage # - BreastProjectionXRayImageStorageForPresentation # - BreastProjectionXRayImageStorageForProcessing +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage # - CompositingPlanarMPRVolumetricPresentationStateStorage # - ContentAssessmentResultsStorage # - CTDefinedProcedureProtocolStorage # - CTPerformedProcedureProtocolStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage # - ExtensibleSRStorage # - GrayscalePlanarMPRVolumetricPresentationStateStorage @@ -878,6 +933,7 @@ Role127 = DRAFT_WaveformStorage\BOTH # - LegacyConvertedEnhancedCTImageStorage # - LegacyConvertedEnhancedMRImageStorage # - LegacyConvertedEnhancedPETImageStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -887,12 +943,20 @@ Role127 = DRAFT_WaveformStorage\BOTH # - PlannedImagingAgentAdministrationSRStorage # - ProtocolApprovalStorage # - RadiopharmaceuticalRadiationDoseSRStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTBrachyApplicationSetupDeliveryInstructionStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage # - SimplifiedAdultEchoSRStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - TractographyResultsStorage # - VolumeRenderingVolumetricPresentationStateStorage # - WideFieldOphthalmicPhotographyStereographicProjectionImageStorage @@ -1044,9 +1108,17 @@ Role127 = XRayRadiationDoseSRStorage\BOTH # the following SOP classes are missing in the above list: # # - AdvancedBlendingPresentationStateStorage +# - BodyPositionWaveformStorage +# - CArmPhotonElectronRadiationRecordStorage # - CArmPhotonElectronRadiationStorage # - ColorPaletteStorage +# - DermoscopicPhotographyImageStorage +# - ElectromyogramWaveformStorage +# - ElectrooculogramWaveformStorage +# - EncapsulatedMTLStorage +# - EncapsulatedOBJStorage # - EncapsulatedSTLStorage +# - MultichannelRespiratoryWaveformStorage # - MultipleVolumeRenderingVolumetricPresentationStateStorage # - OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage # - OphthalmicOpticalCoherenceTomographyEnFaceImageStorage @@ -1054,10 +1126,18 @@ Role127 = XRayRadiationDoseSRStorage\BOTH # - PerformedImagingAgentAdministrationSRStorage # - PlannedImagingAgentAdministrationSRStorage # - ProtocolApprovalStorage +# - RoboticArmRadiationStorage +# - RoboticRadiationRecordStorage +# - RoutineScalpElectroencephalogramWaveformStorage # - RTPhysicianIntentStorage +# - RTRadiationRecordSetStorage +# - RTRadiationSalvageRecordStorage # - RTRadiationSetStorage # - RTSegmentAnnotationStorage # - SegmentedVolumeRenderingVolumetricPresentationStateStorage +# - SleepElectroencephalogramWaveformStorage +# - TomotherapeuticRadiationRecordStorage +# - TomotherapeuticRadiationStorage # - VolumeRenderingVolumetricPresentationStateStorage # # - RETIRED_HardcopyColorImageStorage diff --git a/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h b/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h index 3a1fa001..45e6466a 100644 --- a/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h +++ b/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1993-2017, OFFIS e.V. + * Copyright (C) 1993-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -28,7 +28,7 @@ class DcmQueryRetrieveDatabaseHandle; class DcmQueryRetrieveOptions; -class DcmQueryRetrieveCharacterSetOptions; +struct DcmQueryRetrieveCharacterSetOptions; /** this class maintains the context information that is passed to the * callback function called by DIMSE_findProvider. @@ -45,12 +45,12 @@ public: DcmQueryRetrieveDatabaseHandle& handle, const DcmQueryRetrieveOptions& options, DIC_US priorStat, - const DcmQueryRetrieveCharacterSetOptions& characterSetOptions) + const DcmQueryRetrieveCharacterSetOptions& charSetOptions) : dbHandle(handle) , options_(options) , priorStatus(priorStat) , ourAETitle() - , characterSetOptions(characterSetOptions) + , characterSetOptions(charSetOptions) { } diff --git a/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h b/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h index 9284d68b..03ebfc1b 100644 --- a/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h +++ b/dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h @@ -400,7 +400,7 @@ public: private: - friend class DcmQueryRetrieveCharacterSetOptions; + friend struct DcmQueryRetrieveCharacterSetOptions; const char* vendorForPeerAETitle(const char *peerAETitle) const; diff --git a/dcmqrdb/libsrc/dcmqrcnf.cc b/dcmqrdb/libsrc/dcmqrcnf.cc index 586d3e05..4b4b0bcb 100644 --- a/dcmqrdb/libsrc/dcmqrcnf.cc +++ b/dcmqrdb/libsrc/dcmqrcnf.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1993-2018, OFFIS e.V. + * Copyright (C) 1993-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -28,6 +28,7 @@ #define INCLUDE_CCTYPE #define INCLUDE_CSTDARG #define INCLUDE_CSTRING +#define INCLUDE_CLIMITS #include "dcmtk/ofstd/ofstdinc.h" #include "dcmtk/ofstd/ofcmdln.h" #include "dcmtk/ofstd/ofmap.h" @@ -75,7 +76,7 @@ OFBool DcmQueryRetrieveCharacterSetOptions::parseOptions(const char* mnemonic, c { struct RAIIFree { - RAIIFree(char* ptr) : ptr(ptr) {} + RAIIFree(char* p) : ptr(p) {} ~RAIIFree() {free(ptr);} char* ptr; }; @@ -601,13 +602,13 @@ int DcmQueryRetrieveConfig::readAETable(FILE *cnffp, int *lineno) CNF_Config.AEEntries[noOfAEEntries - 1].StorageArea = parsevalues(&lineptr); CNF_Config.AEEntries[noOfAEEntries - 1].Access = parsevalues(&lineptr); CNF_Config.AEEntries[noOfAEEntries - 1].StorageQuota = parseQuota(&lineptr); - if ((CNF_Config.AEEntries[noOfAEEntries - 1].StorageQuota->maxStudies == 0) || - (CNF_Config.AEEntries[noOfAEEntries - 1].StorageQuota->maxBytesPerStudy == 0)) - error = 1; - else - { - CNF_Config.AEEntries[noOfAEEntries - 1].Peers = parsePeers(&lineptr, &CNF_Config.AEEntries[noOfAEEntries - 1].noOfPeers); - if (!CNF_Config.AEEntries[noOfAEEntries - 1].noOfPeers) error = 1; + CNF_Config.AEEntries[noOfAEEntries - 1].Peers = parsePeers(&lineptr, &CNF_Config.AEEntries[noOfAEEntries - 1].noOfPeers); + + // check the validity of the storage quota and peers values before continuing + if (CNF_Config.AEEntries[noOfAEEntries - 1].StorageQuota->maxStudies == 0 || + CNF_Config.AEEntries[noOfAEEntries - 1].StorageQuota->maxBytesPerStudy == 0 || + CNF_Config.AEEntries[noOfAEEntries - 1].noOfPeers == 0) { + error = 1; } } @@ -651,6 +652,12 @@ DcmQueryRetrieveConfigPeer *DcmQueryRetrieveConfig::parsePeers(char **valuehandl char *valueptr = *valuehandle; helpvalue = parsevalues(valuehandle); + + if (!helpvalue) { + *peers = 0; // indicates error to caller + return NULL; + } + if (!strcmp("ANY", helpvalue)) { /* keyword ANY used */ free(helpvalue); *peers = -1; @@ -854,6 +861,11 @@ long DcmQueryRetrieveConfig::quota (const char *value) else return(-1L); number = atoi(value); + + // check for overflow + if (number > 0 && factor > LONG_MAX / number) + return LONG_MAX; + return(number * factor); } diff --git a/dcmqrdb/libsrc/dcmqrdbi.cc b/dcmqrdb/libsrc/dcmqrdbi.cc index 1ef1ec47..60fdb4af 100644 --- a/dcmqrdb/libsrc/dcmqrdbi.cc +++ b/dcmqrdb/libsrc/dcmqrdbi.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1993-2018, OFFIS e.V. + * Copyright (C) 1993-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -1680,33 +1680,33 @@ OFCondition DcmQueryRetrieveIndexDatabaseHandle::nextFindResponse ( } if (isConversionNecessary(specificCharacterSet, *destinationCharacterSet)) { - OFCondition status = (*findResponseIdentifiers)->convertCharacterSet( + OFCondition charset_status = (*findResponseIdentifiers)->convertCharacterSet( specificCharacterSet, *destinationCharacterSet, characterSetOptions.conversionFlags, OFTrue); - if (status.bad()) { + if (charset_status.bad()) { DCMQRDB_WARN("Converting response from character set \"" << characterSetName(specificCharacterSet) << "\" to character set \"" << characterSetName(*destinationCharacterSet) - << "\" failed, (error message: " << status.text() << ')'); + << "\" failed, (error message: " << charset_status.text() << ')'); if (fallbackCharacterSet && isConversionNecessary(specificCharacterSet, *fallbackCharacterSet)) { DCMQRDB_INFO("Trying to convert response from character set \"" << characterSetName(specificCharacterSet) << "\" to fall-back character set \"" << characterSetName(*fallbackCharacterSet) << "\" instead"); - status = (*findResponseIdentifiers)->convertCharacterSet( + charset_status = (*findResponseIdentifiers)->convertCharacterSet( specificCharacterSet, *fallbackCharacterSet, characterSetOptions.conversionFlags, OFTrue); - if (status.bad()) { + if (charset_status.bad()) { DCMQRDB_WARN("Converting response from character set \"" << characterSetName(specificCharacterSet) << "\" to character set \"" << characterSetName(*fallbackCharacterSet) - << "\" failed, (error message: " << status.text() << ')'); + << "\" failed, (error message: " << charset_status.text() << ')'); } else { DCMQRDB_INFO("Successfully converted response from character set \"" << characterSetName(specificCharacterSet) @@ -1784,7 +1784,7 @@ OFCondition DcmQueryRetrieveIndexDatabaseHandle::nextFindResponse ( } - /**** If an error occured in Matching function + /**** If an error occurred in Matching function **** return status is pending ***/ diff --git a/dcmrt/include/dcmtk/dcmrt/drmdose.h b/dcmrt/include/dcmtk/dcmrt/drmdose.h index 17fa30dc..e2b40431 100644 --- a/dcmrt/include/dcmtk/dcmrt/drmdose.h +++ b/dcmrt/include/dcmtk/dcmrt/drmdose.h @@ -96,7 +96,7 @@ public: * coordinate 0. * @param frame frame to use. The first frame has number 0, the last * frame is getNumberOfFrames()-1. - * @return unscaled dose value for the pixel or 0 if an error occured. + * @return unscaled dose value for the pixel or 0 if an error occurred. */ virtual double getUnscaledDose(unsigned int x, unsigned int y, unsigned int frame = 0) const; diff --git a/dcmrt/libsrc/drtrbs4.cc b/dcmrt/libsrc/drtrbs4.cc index f1c2ef3c..2b7b6643 100644 --- a/dcmrt/libsrc/drtrbs4.cc +++ b/dcmrt/libsrc/drtrbs4.cc @@ -1,13 +1,14 @@ /* * * Copyright (C) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany - * Copyright (C) 2013-2017, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2013-2019, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class DRTReferencedBeamSequenceInRTGeneralTreatmentRecordModule * * Generated automatically from DICOM PS 3.3-2017e * File created on 2017-12-05 09:30:54 + * Last modified on 2019-10-31 by Riesmeier * */ @@ -25,7 +26,7 @@ DRTReferencedBeamSequenceInRTGeneralTreatmentRecordModule::Item::Item(const OFBo AlternateBeamDoseType(DCM_AlternateBeamDoseType), BeamDeliveryDurationLimit(DCM_BeamDeliveryDurationLimit), BeamDose(DCM_BeamDose), - BeamDoseSpecificationPoint(DCM_BeamDoseSpecificationPoint), + BeamDoseSpecificationPoint(DCM_RETIRED_BeamDoseSpecificationPoint), BeamDoseType(DCM_BeamDoseType), BeamMeterset(DCM_BeamMeterset), ReferencedBeamNumber(DCM_ReferencedBeamNumber), diff --git a/dcmrt/libsrc/drtrbs8.cc b/dcmrt/libsrc/drtrbs8.cc index 131cd05b..40b8757d 100644 --- a/dcmrt/libsrc/drtrbs8.cc +++ b/dcmrt/libsrc/drtrbs8.cc @@ -1,13 +1,14 @@ /* * * Copyright (C) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany - * Copyright (C) 2013-2017, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2013-2019, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class DRTReferencedBeamSequenceInRTFractionSchemeModule * * Generated automatically from DICOM PS 3.3-2017e * File created on 2017-12-05 09:30:54 + * Last modified on 2019-10-31 by Riesmeier * */ @@ -25,7 +26,7 @@ DRTReferencedBeamSequenceInRTFractionSchemeModule::Item::Item(const OFBool empty AlternateBeamDoseType(DCM_AlternateBeamDoseType), BeamDeliveryDurationLimit(DCM_BeamDeliveryDurationLimit), BeamDose(DCM_BeamDose), - BeamDoseSpecificationPoint(DCM_BeamDoseSpecificationPoint), + BeamDoseSpecificationPoint(DCM_RETIRED_BeamDoseSpecificationPoint), BeamDoseType(DCM_BeamDoseType), BeamMeterset(DCM_BeamMeterset), ReferencedBeamNumber(DCM_ReferencedBeamNumber), diff --git a/dcmseg/include/dcmtk/dcmseg/segdef.h b/dcmseg/include/dcmtk/dcmseg/segdef.h index 657a6881..dcc5e3b4 100644 --- a/dcmseg/include/dcmtk/dcmseg/segdef.h +++ b/dcmseg/include/dcmtk/dcmseg/segdef.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -19,11 +19,11 @@ * */ - #ifndef SEGDEF_H #define SEGDEF_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/ofstd/ofdefine.h" // definitions for DLL/shared library exports diff --git a/dcmseg/include/dcmtk/dcmseg/segdoc.h b/dcmseg/include/dcmtk/dcmseg/segdoc.h index edd82e8e..3e825da8 100644 --- a/dcmseg/include/dcmtk/dcmseg/segdoc.h +++ b/dcmseg/include/dcmtk/dcmseg/segdoc.h @@ -22,24 +22,23 @@ #ifndef SEGDOC_H #define SEGDOC_H -#include "dcmtk/config/osconfig.h" // include OS configuration first -#include "dcmtk/ofstd/ofvector.h" // for OFVector -#include "dcmtk/dcmiod/iodimage.h" // common image IOD attribute access -#include "dcmtk/dcmiod/iodmacro.h" -#include "dcmtk/dcmiod/modimagepixel.h" -#include "dcmtk/dcmiod/modsegmentationseries.h" // for segmentation series module -#include "dcmtk/dcmiod/modenhequipment.h" // for enhanced general equipment module +#include "dcmtk/config/osconfig.h" // include OS configuration first -#include "dcmtk/dcmiod/modmultiframefg.h" // for multi-frame functional group module -#include "dcmtk/dcmiod/modmultiframedimension.h"// for multi-frame dimension module #include "dcmtk/dcmdata/dcvrui.h" - -#include "dcmtk/dcmfg/fginterface.h" // for multi-frame functional group interface -#include "dcmtk/dcmfg/fgfracon.h" // for frame content functional group macro - -#include "dcmtk/dcmseg/segtypes.h" // for segmentation data types +#include "dcmtk/dcmfg/concatenationcreator.h" // for writing concatenations +#include "dcmtk/dcmfg/concatenationloader.h" // for loading concatenations +#include "dcmtk/dcmfg/fgfracon.h" // for frame content functional group macro +#include "dcmtk/dcmfg/fginterface.h" // for multi-frame functional group interface +#include "dcmtk/dcmiod/iodimage.h" // common image IOD attribute access +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modenhequipment.h" // for enhanced general equipment module +#include "dcmtk/dcmiod/modimagepixel.h" +#include "dcmtk/dcmiod/modmultiframedimension.h" // for multi-frame dimension module +#include "dcmtk/dcmiod/modmultiframefg.h" // for multi-frame functional group module +#include "dcmtk/dcmiod/modsegmentationseries.h" // for segmentation series module #include "dcmtk/dcmseg/segdef.h" - +#include "dcmtk/dcmseg/segtypes.h" // for segmentation data types +#include "dcmtk/ofstd/ofvector.h" // for OFVector // Forward declarations class DcmSegment; @@ -48,638 +47,632 @@ class FGDerivationImage; /** Class representing an object of the "Segmentation SOP Class". */ -class DCMTK_DCMSEG_EXPORT DcmSegmentation -: public DcmIODImage > +class DCMTK_DCMSEG_EXPORT DcmSegmentation : public DcmIODImage > { public: - - // -------------------- destruction ------------------------------- - - /** Destructor, frees memory - */ - virtual ~DcmSegmentation(); - - // -------------------- loading and saving --------------------- - - /** Static method to load a Segmentation object from a file. - * The memory of the resulting Segmentation object has to be freed by the - * caller. - * @param filename The file to read from - * @param segmentation The resulting segmentation object. NULL if dataset - * could not be read successfully. - * @return EC_Normal if reading was successful, error otherwise - */ - static OFCondition loadFile(const OFString& filename, - DcmSegmentation*& segmentation); - - /** Static method to load a Segmentation object from a dataset object. - * The memory of the resulting Segmentation object has to be freed by the - * caller. - * @param dataset The dataset to read from - * @param segmentation The resulting segmentation object. NULL if dataset - * could not be read successfully. - * @return EC_Normal if reading was successful, error otherwise - */ - static OFCondition loadDataset(DcmDataset& dataset, - DcmSegmentation*& segmentation); - - /** Save current object to given filename - * @param filename The file to write to - * @param writeXfer The transfer syntax to be used - * @return EC_Normal if writing was successful, error otherwise. - */ - OFCondition saveFile(const OFString& filename, - const E_TransferSyntax writeXfer = EXS_LittleEndianExplicit); - - /** Write current object to given item - * @param dataset The item to write to - * @return EC_Normal if writing was successful, error otherwise. - */ - OFCondition writeDataset(DcmItem& dataset); - - /** If enabled, functional group structure is checked before actual writing - * is performed in the write() method. Checking might be time consuming - * on functional groups with many frames, though disabling might result in - * invalid functional group structures. Disabling should only be done if the - * user knows that the functional groups are valid, wants to to adapt the - * functional groups manually after calling write() or knows what he's doing - * otherwise.
- * Per default, checking is enabled. - * @param doCheck If OFTrue, checking will be performed. If OFFalse, - * no checks are performed. - */ - virtual void setCheckFGOnWrite(const OFBool doCheck); - - /** Returns whether functional group structure is checked before actual - * writing is performed in the write() method. - * @return OFTrue if checking is performed, OFFalse otherwise - */ - virtual OFBool getCheckFGOnWrite(); - - - // -------------------- creation --------------------- - - /** Factory method to create a binary segmentation object from the minimal - * set of information required. The actual segments and the frame data is - * added separately. - * The memory of the resulting Segmentation object has to be freed by the - * caller. - * @param segmentation The resulting segmentation object if provided data is - * valid. Otherwise NULL is returned. - * @param rows Number of rows of segmentation frame data - * @param columns Number of rows of segmentation frame data - * @param equipmentInfo Equipment that is responsible for creating the - * segmentation - * @param contentIdentification Basic content identification information - * @return EC_Normal if creation was successful, error otherwise - */ - static OFCondition createBinarySegmentation(DcmSegmentation*& segmentation, - const Uint16 rows, - const Uint16 columns, - const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, - const ContentIdentificationMacro& contentIdentification); - - /** Factory method to create a fractional segmentation object from the minimal - * set of information required. The actual segments and the frame data is - * added separately. - * The memory of the resulting Segmentation object has to be freed by the - * caller. - * @param segmentation The resulting segmentation object if provided data is - * valid. Otherwise NULL is returned. - * @param rows Number of rows of segmentation frame data - * @param columns Number of rows of segmentation frame data - * @param fractType Either probability (SFT_PROBABILITY) or - * occupancy (SFT_OCCUPANCY) - * @param maxFractionalValue The value inside the frame data of this - * segmentation that represents 100% occupancy/probability - * @param equipmentInfo Equipment that is responsible for creating the - * segmentation - * @param contentIdentification Basic content identification information - * @return EC_Normal if creation was successful, error otherwise - */ - static OFCondition createFractionalSegmentation(DcmSegmentation*& segmentation, - const Uint16 rows, - const Uint16 columns, - const DcmSegTypes::E_SegmentationFractionalType fractType, - const Uint16& maxFractionalValue, - const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, - const ContentIdentificationMacro& contentIdentification); - - /** Helps to create a valid Derivation Image Functional Group Macro - * The memory of the resulting functional group object has to be freed by the - * caller. - * @param derivationImages to image SOP instances - * @param derivationDescription Free text describing how the derivation was - * achieved. - * @return The created functional group, or NULL if not successful - */ - static FGDerivationImage* createDerivationImageFG(const OFVector& derivationImages, - const OFString& derivationDescription); - - // -------------------- access --------------------- - - /** Get number of frames, based on the number of items in the shared - * functional functional groups sequence (i.e.\ the attribute Number of - * Frames) is not trusted). - * @return The number of frames handled by this object - */ - size_t getNumberOfFrames(); - - /** Get Segmentation Type - * @return Type of the segmentation, as defined by DcmSegTypes::E_SegmentationType - */ - DcmSegTypes::E_SegmentationType getSegmentationType() - { - return this->m_SegmentationType; - } - - /** Get Fractional Segmentation Type - * @return Type of the segmentation, as defined by - * DcmSegTypes::E_SegmentationFractionalTypes (returns SFT_UNKNOWN if not - * fractional at all) - */ - DcmSegTypes::E_SegmentationFractionalType getSegmentationFractionalType() - { - return this->m_SegmentationFractionalType; - } - - /** Get the Number of Segments - * @return The number of segments handled by this object - */ - size_t getNumberOfSegments(); - - /** Perform some basic checking. This method is also invoked when - * writing the object to a DICOM dataset or file. - * @param checkFGStructure If OFTrue (default), structure of functional - * groups is checked, too. - * @return OFTrue, if no errors were found, OFFalse otherwise. - */ - virtual OFBool check(const OFBool checkFGStructure = OFTrue); - - /** Get access to functional groups. This is meant for reading data from - * functional groups that are not actively managed, i.e.\ made accessible by - * DcmSegmentation. In rare cases, however, it makes sense to access it - * for writing too, e.g.\ in order to add Stacks; use with care! - * @return Reference to the functional groups - */ - virtual FGInterface& getFunctionalGroups(); - - /** Get General Equipment Module - * @return General Equipment Module - */ - virtual IODGeneralEquipmentModule& getEquipment(); - - /** Get Segmentation Series Module - * @return Segmentation Series Module - */ - virtual IODSegmentationSeriesModule& getSegmentationSeriesModule(); - - /** Get modality (overwrite from DcmIODCommon. We always return "SEG" here) - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get. Not evaluated (here for - * consistency with other setter functions). - * @return status, EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getModality(OFString &value, - const signed long pos = 0) const; - - /** Get segment by providing the logical segment number - * @param segmentNumber The logical segment number - * @return The segment if segment number is valid, NULL otherwise - */ - virtual DcmSegment* getSegment(const unsigned int segmentNumber); - - /** Get logical segment number by providing a pointer to a given segment - * @param segment The segment to find the logical segment number for - * @param segmentNumber The segment number. 0 if segment could not be found. - * @return OFTrue if segment could be found, OFFalse otherwise. - */ - virtual OFBool getSegmentNumber(const DcmSegment* segment, - unsigned int& segmentNumber); - - /** Reference to the Performed Procedure Step that led to the creation of this - * segmentation object. This is required if this object is created in an MPPS - * or GPPS workflow. - * @return Reference to the referenced PPS object - */ - virtual SOPInstanceReferenceMacro& getReferencedPPS(); - - /** Get (const) frame data of a specific frame - * @param frameNo The number of the frame to get (starting with 0) - * @return The frame requested or NULL if not existing - */ - virtual const DcmIODTypes::Frame* getFrame(const size_t& frameNo); - - /** Get the frame numbers that belong to a specific segment number - * @param segmentNumber The segment to search frames for - * @param frameNumbers The frame numbers belonging to that segment - */ - virtual void getFramesForSegment(const size_t& segmentNumber, - OFVector& frameNumbers); - - // -------------------- modification --------------------- - - /** Add segment to segmentation object - * @param seg The segment that should be added - * @param segmentNumber The logical segment number that was assigned for - * this segment. Contains 0 if adding failed. - * @return EC_Normal if adding was successful, error otherwise - */ - virtual OFCondition addSegment(DcmSegment* seg, - Uint16& segmentNumber); - - /** Add a functional group for all frames - * @param group The group to be added as shared functional group. The - * @return EC_Normal if adding was successful, error otherwise - */ - virtual OFCondition addForAllFrames(const FGBase& group); - - /** Add frame to segmentation object - * @param pixData Pixel data to be added. Length must be rows*columns bytes. - * For binary segmentations (bit depth i.e.\ Bits - * Allocated/Stored=1), each byte equal to 0 will be interpreted as - * "not set", while every other value is interpreted as "set". For - * fractional segmentations the full byte is copied as is. - * @param segmentNumber The logical segment number (>=1) this frame refers to. - * The segment identified by the segmentNumber must already exist. - * @param perFrameInformation The functional groups that identify this frame (i.e. - * which are planned to be not common for all other frames). The - * functional groups are copied, so ownership of each group stays - * with the caller no matter what the method returns. - * @return EC_Normal if adding was successful, error otherwise - */ - virtual OFCondition addFrame(Uint8* pixData, - const Uint16 segmentNumber, - const OFVector& perFrameInformation); - - /** Return reference to content content identification of this segmentation object - * @return Reference to content identification data - */ - virtual ContentIdentificationMacro& getContentIdentification(); - - /** Return reference to multi-fame dimension module - * @return Reference to multi-frame dimension module - */ - virtual IODMultiframeDimensionModule& getDimensions(); - - /** Set lossy compression flag of the segmentation object to "01". If one of the - * source images of this segmentation has undergone lossy compression then - * this function should be called. - * @param ratios Compression ratios (separated by backslash) of the applied - * lossy compression steps. Only one value (and no backslash) if only - * one step was performed. - * @param methods Methods (separated by backslash) of the applied - * lossy compression steps. Only one value (and no backslash) if only - * one step was performed. - * @param checkValues If OFTrue, the data provided is checked for validity - * @return EC_Normal if lossy compression info could be set, error code otherwise - */ - virtual OFCondition setLossyImageCompressionFlag(const OFString& ratios, - const OFString& methods, - const OFBool checkValues = OFTrue); - - /** Set equipment info for this segmentation object - * @param equipmentInfo The description of the equipment used to create - * this segmentation - * @param checkValue If OFTrue, the data provided is checked for validity - * @return EC_Normal if equipment information could be set successfully, error otherwise - */ - virtual OFCondition setEquipmentInfo(const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, - const OFBool checkValue = OFTrue); - - /** Set content identification info for this segmentation object - * @param contentIdentification The content identification of this segmentation - * @param checkValue If OFTrue, the data provided is checked for validity - * (as possible) - * @return EC_Normal if content identification could be set correctly, OFFalse otherwise - */ - virtual OFCondition setContentIdentification(const ContentIdentificationMacro& contentIdentification, - const OFBool checkValue = OFTrue); - - /** Import Patient, Study, and Frame of Reference level information from the - * given item. The method does only import Frame of Reference if Frame of - * Reference (FoR) UID is found in the image (and no error is reported if not). - * The reason is that if the source images of the segmentation do have an - * FoR, the segmentation object must have the same one, so we must import it. - * If the images do not have an FoR, we must not try at all importing it. - * If the log stream is set and valid the, the reason for any error might be - * obtained from the error/warning output. - * @param dataset Reference to DICOM dataset from which the document - * should be read - * @param takeOverCharset If OFTrue (default), Specific Character Set is - * taken over from imported dataset. If it's not - * present or empty (invalid), the attribute will - * not be present in this class either. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition importFromSourceImage(DcmItem& dataset, - const OFBool takeOverCharset = OFTrue); - - /** Import Patient, Study, and Frame of Reference level information from the - * given item. The method does only import Frame of Reference if Frame of - * Reference UID is found in the image (and no error is reported if not). - * The reason is that if the source images of the segmentation do have an - * FoR, the segmentation object must have the same one, so we must import it. - * If the images do not have an FoR, we must not try at all importing it. - * The current content of this object is not deleted before reading. - * If the log stream is set and valid the, the reason for any error might be - * obtained from the error/warning output. - * @param filename Reference to DICOM dataset from which the document - * should be read - * @param takeOverCharset If OFTrue (default), Specific Character Set is - * taken over from imported dataset. If it's not - * present or empty (invalid), the attribute will - * not be present in this class either. - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition importFromSourceImage(const OFString& filename, - const OFBool takeOverCharset = OFTrue); + // -------------------- destruction ------------------------------- + + /** Destructor, frees memory + */ + virtual ~DcmSegmentation(); + + // -------------------- loading and saving --------------------- + + /** Static method to load a Segmentation object from a file. + * The memory of the resulting Segmentation object has to be freed by the + * caller. + * @param filename The file to read from + * @param segmentation The resulting segmentation object. NULL if dataset + * could not be read successfully. + * @return EC_Normal if reading was successful, error otherwise + */ + static OFCondition loadFile(const OFString& filename, DcmSegmentation*& segmentation); + + /** Static method to load a Segmentation object from a dataset object. + * The memory of the resulting Segmentation object has to be freed by the + * caller. + * @param dataset The dataset to read from + * @param segmentation The resulting segmentation object. NULL if dataset + * could not be read successfully. + * @return EC_Normal if reading was successful, error otherwise + */ + static OFCondition loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation); + + /** Static method to load a concatenation of a DICOM Segmentation instance + * into a DcmSegmentation object. + * @param cl The ConcatenationLoader instance to be used. Must be configured + * so that load() can be called. + * @param concatenationUID The Concatenation UID identifying the Concatenation + * within the Concatenations know to ConcatenationLoader cl. + * @param segmentation The resulting Segmentation object, if loading was successful + * @return EC_Normal if loading was successful, error otherwise + */ + static OFCondition + loadConcatenation(ConcatenationLoader& cl, const OFString& concatenationUID, DcmSegmentation*& segmentation); + + /** Save current object to given filename + * @param filename The file to write to + * @param writeXfer The transfer syntax to be used + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition saveFile(const OFString& filename, const E_TransferSyntax writeXfer = EXS_LittleEndianExplicit); + + /** Write current object to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition writeDataset(DcmItem& dataset); + + /** Write current object to a Concatenation. + * @param cc The Concatenation Creator object to be used. Must be configured + * so that writeNextInstance() is ready to be called. + * @return EC_Normal if writing was successful, error otherwise. + */ + OFCondition writeConcatenation(ConcatenationCreator& cc); + + /** If enabled, functional group structure is checked before actual writing + * is performed in the write() method. Checking might be time consuming + * on functional groups with many frames, though disabling might result in + * invalid functional group structures. Disabling should only be done if the + * user knows that the functional groups are valid, wants to to adapt the + * functional groups manually after calling write() or knows what he's doing + * otherwise.
+ * Per default, checking is enabled. + * @param doCheck If OFTrue, checking will be performed. If OFFalse, + * no checks are performed. + */ + virtual void setCheckFGOnWrite(const OFBool doCheck); + + /** Returns whether functional group structure is checked before actual + * writing is performed in the write() method. + * @return OFTrue if checking is performed, OFFalse otherwise + */ + virtual OFBool getCheckFGOnWrite(); + + // -------------------- creation --------------------- + + /** Factory method to create a binary segmentation object from the minimal + * set of information required. The actual segments and the frame data is + * added separately. + * The memory of the resulting Segmentation object has to be freed by the + * caller. + * @param segmentation The resulting segmentation object if provided data is + * valid. Otherwise NULL is returned. + * @param rows Number of rows of segmentation frame data + * @param columns Number of rows of segmentation frame data + * @param equipmentInfo Equipment that is responsible for creating the + * segmentation. All attributes in equipmentInfo must have + * non-empty values. + * @param contentIdentification Basic content identification information + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition createBinarySegmentation(DcmSegmentation*& segmentation, + const Uint16 rows, + const Uint16 columns, + const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const ContentIdentificationMacro& contentIdentification); + + /** Factory method to create a fractional segmentation object from the minimal + * set of information required. The actual segments and the frame data is + * added separately. + * The memory of the resulting Segmentation object has to be freed by the + * caller. + * @param segmentation The resulting segmentation object if provided data is + * valid. Otherwise NULL is returned. + * @param rows Number of rows of segmentation frame data + * @param columns Number of rows of segmentation frame data + * @param fractType Either probability (SFT_PROBABILITY) or + * occupancy (SFT_OCCUPANCY) + * @param maxFractionalValue The value inside the frame data of this + * segmentation that represents 100% occupancy/probability + * @param equipmentInfo Equipment that is responsible for creating the + * segmentation. All attributes in equipmentInfo must have + * non-empty values. + * @param contentIdentification Basic content identification information + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition createFractionalSegmentation(DcmSegmentation*& segmentation, + const Uint16 rows, + const Uint16 columns, + const DcmSegTypes::E_SegmentationFractionalType fractType, + const Uint16& maxFractionalValue, + const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const ContentIdentificationMacro& contentIdentification); + + /** Helps to create a valid Derivation Image Functional Group Macro + * The memory of the resulting functional group object has to be freed by the + * caller. + * @param derivationImages to image SOP instances + * @param derivationDescription Free text describing how the derivation was + * achieved. + * @return The created functional group, or NULL if not successful + */ + static FGDerivationImage* createDerivationImageFG(const OFVector& derivationImages, + const OFString& derivationDescription); + + // -------------------- access --------------------- + + /** Get number of frames, based on the number of items in the shared + * functional functional groups sequence (i.e.\ the attribute Number of + * Frames) is not trusted). + * @return The number of frames handled by this object + */ + size_t getNumberOfFrames(); + + /** Get Segmentation Type + * @return Type of the segmentation, as defined by DcmSegTypes::E_SegmentationType + */ + DcmSegTypes::E_SegmentationType getSegmentationType() + { + return this->m_SegmentationType; + } + + /** Get Fractional Segmentation Type + * @return Type of the segmentation, as defined by + * DcmSegTypes::E_SegmentationFractionalTypes (returns SFT_UNKNOWN if not + * fractional at all) + */ + DcmSegTypes::E_SegmentationFractionalType getSegmentationFractionalType() + { + return this->m_SegmentationFractionalType; + } + + /** Get the Number of Segments + * @return The number of segments handled by this object + */ + size_t getNumberOfSegments(); + + /** Perform some basic checking. This method is also invoked when + * writing the object to a DICOM dataset or file. + * @param checkFGStructure If OFTrue (default), structure of functional + * groups is checked, too. + * @return OFTrue, if no errors were found, OFFalse otherwise. + */ + virtual OFBool check(const OFBool checkFGStructure = OFTrue); + + /** Get access to functional groups. This is meant for reading data from + * functional groups that are not actively managed, i.e.\ made accessible by + * DcmSegmentation. In rare cases, however, it makes sense to access it + * for writing too, e.g.\ in order to add Stacks; use with care! + * @return Reference to the functional groups + */ + virtual FGInterface& getFunctionalGroups(); + + /** Get reference t Concatenation information + * @return Reference to ConcatenationInfo object + */ + virtual IODMultiFrameFGModule::ConcatenationInfo& getConcatenationInfo(); + + /** Get General Equipment Module + * @return General Equipment Module + */ + virtual IODGeneralEquipmentModule& getEquipment(); + + /** Get Segmentation Series Module + * @return Segmentation Series Module + */ + virtual IODSegmentationSeriesModule& getSegmentationSeriesModule(); + + /** Get modality (overwrite from DcmIODCommon. We always return "SEG" here) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get. Not evaluated (here for + * consistency with other setter functions). + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString& value, const signed long pos = 0) const; + + /** Get segment by providing the logical segment number + * @param segmentNumber The logical segment number + * @return The segment if segment number is valid, NULL otherwise + */ + virtual DcmSegment* getSegment(const unsigned int segmentNumber); + + /** Get logical segment number by providing a pointer to a given segment + * @param segment The segment to find the logical segment number for + * @param segmentNumber The segment number. 0 if segment could not be found. + * @return OFTrue if segment could be found, OFFalse otherwise. + */ + virtual OFBool getSegmentNumber(const DcmSegment* segment, unsigned int& segmentNumber); + + /** Reference to the Performed Procedure Step that led to the creation of this + * segmentation object. This is required if this object is created in an MPPS + * or GPPS workflow. + * @return Reference to the referenced PPS object + */ + virtual SOPInstanceReferenceMacro& getReferencedPPS(); + + /** Get (const) frame data of a specific frame + * @param frameNo The number of the frame to get (starting with 0) + * @return The frame requested or NULL if not existing + */ + virtual const DcmIODTypes::Frame* getFrame(const size_t& frameNo); + + /** Get the frame numbers that belong to a specific segment number + * @param segmentNumber The segment to search frames for + * @param frameNumbers The frame numbers belonging to that segment + */ + virtual void getFramesForSegment(const size_t& segmentNumber, OFVector& frameNumbers); + + // -------------------- modification --------------------- + + /** Add segment to segmentation object + * @param seg The segment that should be added + * @param segmentNumber The logical segment number that was assigned for + * this segment. Contains 0 if adding failed. + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition addSegment(DcmSegment* seg, Uint16& segmentNumber); + + /** Add a functional group for all frames + * @param group The group to be added as shared functional group. The + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition addForAllFrames(const FGBase& group); + + /** Add frame to segmentation object + * @param pixData Pixel data to be added. Length must be rows*columns bytes. + * For binary segmentations (bit depth i.e.\ Bits + * Allocated/Stored=1), each byte equal to 0 will be interpreted as + * "not set", while every other value is interpreted as "set". For + * fractional segmentations the full byte is copied as is. + * @param segmentNumber The logical segment number (>=1) this frame refers to. + * The segment identified by the segmentNumber must already exist. + * @param perFrameInformation The functional groups that identify this frame (i.e. + * which are planned to be not common for all other frames). The + * functional groups are copied, so ownership of each group stays + * with the caller no matter what the method returns. + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition + addFrame(Uint8* pixData, const Uint16 segmentNumber, const OFVector& perFrameInformation); + + /** Return reference to content content identification of this segmentation object + * @return Reference to content identification data + */ + virtual ContentIdentificationMacro& getContentIdentification(); + + /** Return reference to multi-fame dimension module + * @return Reference to multi-frame dimension module + */ + virtual IODMultiframeDimensionModule& getDimensions(); + + /** Set lossy compression flag of the segmentation object to "01". If one of the + * source images of this segmentation has undergone lossy compression then + * this function should be called. + * @param ratios Compression ratios (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. + * @param methods Methods (separated by backslash) of the applied + * lossy compression steps. Only one value (and no backslash) if only + * one step was performed. + * @param checkValues If OFTrue, the data provided is checked for validity + * @return EC_Normal if lossy compression info could be set, error code otherwise + */ + virtual OFCondition + setLossyImageCompressionFlag(const OFString& ratios, const OFString& methods, const OFBool checkValues = OFTrue); + + /** Set equipment info for this segmentation object + * @param equipmentInfo The description of the equipment used to create + * this segmentation + * @param checkValue If OFTrue, the data provided is checked for validity + * @return EC_Normal if equipment information could be set successfully, error otherwise + */ + virtual OFCondition setEquipmentInfo(const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const OFBool checkValue = OFTrue); + + /** Set content identification info for this segmentation object + * @param contentIdentification The content identification of this segmentation + * @param checkValue If OFTrue, the data provided is checked for validity + * (as possible) + * @return EC_Normal if content identification could be set correctly, OFFalse otherwise + */ + virtual OFCondition setContentIdentification(const ContentIdentificationMacro& contentIdentification, + const OFBool checkValue = OFTrue); + + /** Import Patient, Study, and Frame of Reference level information from the + * given item. The method does only import Frame of Reference if Frame of + * Reference (FoR) UID is found in the image (and no error is reported if not). + * The reason is that if the source images of the segmentation do have an + * FoR, the segmentation object must have the same one, so we must import it. + * If the images do not have an FoR, we must not try at all importing it. + * If the log stream is set and valid the, the reason for any error might be + * obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition importFromSourceImage(DcmItem& dataset, const OFBool takeOverCharset = OFTrue); + + /** Import Patient, Study, and Frame of Reference level information from the + * given item. The method does only import Frame of Reference if Frame of + * Reference UID is found in the image (and no error is reported if not). + * The reason is that if the source images of the segmentation do have an + * FoR, the segmentation object must have the same one, so we must import it. + * If the images do not have an FoR, we must not try at all importing it. + * The current content of this object is not deleted before reading. + * If the log stream is set and valid the, the reason for any error might be + * obtained from the error/warning output. + * @param filename Reference to DICOM dataset from which the document + * should be read + * @param takeOverCharset If OFTrue (default), Specific Character Set is + * taken over from imported dataset. If it's not + * present or empty (invalid), the attribute will + * not be present in this class either. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition importFromSourceImage(const OFString& filename, const OFBool takeOverCharset = OFTrue); protected: - - /** Protected default constructor. Library users should the factory create..() - * method in order to create an object from scratch - */ - DcmSegmentation(); - - /** Overwrites DcmIODImage::read() - * @param dataset The dataset to read from - * @return EC_Normal if reading succeeded, error otherwise - */ - OFCondition read(DcmItem &dataset); - - /** Overwrites DcmIODImage::write() - * @param dataset The dataset to write to - * @return EC_Normal if writing succeeded, error otherwise - */ - OFCondition write(DcmItem &dataset); - - /** Create those data structures common for binary and fractional - * segmentations - * @param segmentation The segmentation object created - * @param rows The number of rows for the segmentation - * @param columns The number of columns for the segmentation - * @param equipmentInfo Equipment information - * @param contentIdentification Content meta information - * @return EC_Normal if creation was successful, error otherwise - */ - static OFCondition createCommon(DcmSegmentation*& segmentation, - const Uint16 rows, - const Uint16 columns, - const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, - const ContentIdentificationMacro& contentIdentification); - - /** Hide same function from IODImage since do not want the user to access - * the image pixel module manually. - * @return The Image Pixel Module - */ - virtual IODImagePixelModule& getImagePixel(); - - /** Initialize IOD rules - */ - virtual void initIODRules(); - - /** Read segments from given item - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readSegments(DcmItem& item); - - /** Write fractional frames to given item - * @param dataset The item to write to, usually main dataset level - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeFractionalFrames(DcmItem& dataset); - - /** Write binary frames to given item - * @param dataset The item to write to, usually main dataset level - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeBinaryFrames(DcmItem& dataset); - - - /** Write Segmentation Image Module - * @param dataset The item to write to, usually main dataset level - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeSegmentationImageModule(DcmItem& dataset); - - /** Write Segments - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeSegments(DcmItem& item); - - /** Write Multi-Frame Functional Groups - * @param dataset The item to write to, usually main dataset level - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeMultiFrameFunctionalGroupsModule(DcmItem& dataset); - - /** Write Multi-Frame Dimension Module - * @param dataset The item to write to, usually main dataset level - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeMultiFrameDimensionModule(DcmItem& dataset); - - /** Read frames - * @param dataset Item to read from, usually main dataset level - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readFrames(DcmItem& dataset); - - /** Get Image Pixel module attributes and perform some basic checking - * @param dataset Item to read from, usually main dataset level - * @param allocated Bits Allocated - * @param stored Bits Stored - * @param high High Bit - * @param spp Samples Per Pixel - * @param pixelRep Pixel Representation - * @param rows Rows - * @param cols Columns - * @param numberOfFrames The number of frames (as set in the dataset) - * @param colorModel The color model used - * @return EC_Normal if reading/checking was successful, error otherwise - */ - virtual OFCondition getAndCheckImagePixelAttributes(DcmItem& dataset, - Uint16& allocated, - Uint16& stored, - Uint16& high, - Uint16& spp, - Uint16& pixelRep, - Uint16& rows, - Uint16& cols, - Uint16& numberOfFrames, - OFString& colorModel); - - /** Extracts Frame structures from the given pixel data element. Only - * applicable for binary segmentations. Within the pixel data element, all - * frames are packed next to each other, with the end of one frame and the - * beginning of the next frame packed bit by bit next to each other. The - * resulting Frames are a bit-by-bit copy of their original counterpart. - * However, their first bit is aligned to the first bit/byte in the Frame, - * and the unused bits in the last byte (if any) are zeroed out. - * @param pixData The pixel data to read from - * @param numFrames The number of frames to read - * @param bitsPerFrame The number of bits per frame (usually rows * columns) - * @param results The resulting frames. Memory for the frames is allocated - * by the method, so the Vector can/should be empty before calling. - * @result Return EC_Normal on success, error otherwise - */ - virtual OFCondition extractFrames(Uint8* pixData, - const size_t numFrames, - const size_t bitsPerFrame, - OFVector< DcmIODTypes::Frame* >& results); - - /** This is the counterpart to the extractFrames() function. It takes a number - * of frames that are in binary segmentation format (i.e. "bit-packed") and - * concatenates them together so the resulting memory block fits the Pixel - * Data format for binary segmentations. Thus method ensure that frames - * are aligned bit for bit concatenated to each other with only (if - * applicable) having unused bits after the last frame. - * @param frames The source frames - * @param pixData The pixel data element data to be filled. Size must be - * at least bitsPerFrame * number of frames. - * @param bitsPerFrame Bits required per frame, usually rows * columns - */ - virtual void concatFrames(OFVector< DcmIODTypes::Frame* > frames, - Uint8* pixData, - const size_t bitsPerFrame); - - /** Add frame to segmentation object. - * @param pixData Pixel data to be added. Length must be rows*columns bytes. - * Pixel data is copied so it must be freed by the caller. - * @return EC_Normal if adding was successful, error otherwise - */ - virtual OFCondition addFrame(Uint8* pixData); + /** Protected default constructor. Library users should the factory create..() + * method in order to create an object from scratch + */ + DcmSegmentation(); + + /** Overwrites DcmIODImage::read() + * @param dataset The dataset to read from + * @return EC_Normal if reading succeeded, error otherwise + */ + OFCondition read(DcmItem& dataset); + + /** Reads dataset without pixel data + * @param dataset The dataset to read from + * @return EC_Normal if reading succeeded, error otherwise + */ + OFCondition readWithoutPixelData(DcmItem& dataset); + + /** Writes the complete dataset without pixel data + * @param dataset The dataset to write to + * @param pixData Buffer for pixel data to write to + * @param pixDataLength Length of pixData buffer + * @return EC_Normal if writing succeeded, error otherwise + */ + OFCondition writeWithSeparatePixelData(DcmItem& dataset, Uint8*& pixData, size_t& pixDataLength); + + /** Create those data structures common for binary and fractional + * segmentations + * @param segmentation The segmentation object created + * @param rows The number of rows for the segmentation + * @param columns The number of columns for the segmentation + * @param equipmentInfo Equipment information + * @param contentIdentification Content meta information + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition createCommon(DcmSegmentation*& segmentation, + const Uint16 rows, + const Uint16 columns, + const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, + const ContentIdentificationMacro& contentIdentification); + + /** Hide same function from IODImage since do not want the user to access + * the image pixel module manually. + * @return The Image Pixel Module + */ + virtual IODImagePixelModule& getImagePixel(); + + /** Initialize IOD rules + */ + virtual void initIODRules(); + + /** Read segments from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSegments(DcmItem& item); + + /** Write fractional frames to given pixel data buffer + * @param pixData The filled pixel data buffer returned by the method + * @param numFrames The number of frames to write + * @param pixDataLength The length of buffer in pixData (in bytes) returned by this method. + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeFractionalFrames(Uint8* pixData, Uint32 numFrames, const size_t pixDataLength); + + /** Write binary frames to given given pixel data buffer + * @param pixData The filled pixel data buffer returned by the method + * @param rows Number of rows in frame + * @param cols Number of columns in frame + * @param pixDataLength The length of buffer in pixData (in bytes) returned by this method. + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeBinaryFrames(Uint8* pixData, Uint16 rows, Uint16 cols, const size_t pixDataLength); + + /** Write Segmentation Image Module + * @param dataset The item to write to, usually main dataset level + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeSegmentationImageModule(DcmItem& dataset); + + /** Write Segments + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeSegments(DcmItem& item); + + /** Write Multi-Frame Functional Groups + * @param dataset The item to write to, usually main dataset level + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeMultiFrameFunctionalGroupsModule(DcmItem& dataset); + + /** Write Multi-Frame Dimension Module + * @param dataset The item to write to, usually main dataset level + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeMultiFrameDimensionModule(DcmItem& dataset); + + /** Read frames + * @param dataset Item to read from, usually main dataset level + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readFrames(DcmItem& dataset); + + /** Get Image Pixel module attributes and perform some basic checking + * @param dataset Item to read from, usually main dataset level + * @param allocated Bits Allocated + * @param stored Bits Stored + * @param high High Bit + * @param spp Samples Per Pixel + * @param pixelRep Pixel Representation + * @param rows Rows + * @param cols Columns + * @param numberOfFrames The number of frames (as set in the dataset) + * @param colorModel The color model used + * @return EC_Normal if reading/checking was successful, error otherwise + */ + virtual OFCondition getAndCheckImagePixelAttributes(DcmItem& dataset, + Uint16& allocated, + Uint16& stored, + Uint16& high, + Uint16& spp, + Uint16& pixelRep, + Uint16& rows, + Uint16& cols, + Uint16& numberOfFrames, + OFString& colorModel); + + /** This is the counterpart to the extractFrames() function. It takes a number + * of frames that are in binary segmentation format (i.e. "bit-packed") and + * concatenates them together so the resulting memory block fits the Pixel + * Data format for binary segmentations. Thus method ensure that frames + * are aligned bit for bit concatenated to each other with only (if + * applicable) having unused bits after the last frame. + * @param frames The source frames + * @param pixData The pixel data element data to be filled. Size must be + * at least bitsPerFrame * number of frames. + * @param bitsPerFrame Bits required per frame, usually rows * columns + */ + virtual void concatFrames(OFVector frames, Uint8* pixData, const size_t bitsPerFrame); + + /** Add frame to segmentation object. + * @param pixData Pixel data to be added. Length must be rows*columns bytes. + * Pixel data is copied so it must be freed by the caller. + * @return EC_Normal if adding was successful, error otherwise + */ + virtual OFCondition addFrame(Uint8* pixData); private: - - // Modules supported: - // - // Patient Module (through DcmIODImage) - // Patient Study Module (through DcmIODImage) - // General Study Module (through DcmIODImage) - // General Series Module (through DcmIODImage) - // Segmentation Series Module - // Frame of Reference Module (through DcmIODImage) - // General Equipment Module (through DcmIODImage) - // Enhanced General Equipment Module (through DcmIODImage) - // General Image Module (through DcmIODImage) - // Image Pixel Module (through DcmIODImage) - // Segmentation Image Module (through this class) - // Multi-frame Functional Group Module - // Multi-Frame Dimension Module - // SOP Common Module (through DcmIODImage) - // Common Instance Reference Module (through DcmIODImage) - - /// Segmentation Series Module - IODSegmentationSeriesModule m_SegmentationSeries; - - /// IODEnhancedEquipmentModule - IODEnhGeneralEquipmentModule m_EnhancedGeneralEquipmentModule; - - /// Multi-frame Functional Groups module - IODMultiFrameFGModule m_FG; - - /// Multi-frame Dimension Module - IODMultiframeDimensionModule m_DimensionModule; - - /// Binary frame data - OFVector m_Frames; - - /* Image level information */ - - /// Image Type: (CS, VM 2-n, Type 1), in Segmentations fixed to "DERIVED\PRIMARY" - const OFString m_ImageType; - - // Instance Number: (IS, VM 1, Type 1) - - /// Content Identification Macro - ContentIdentificationMacro m_ContentIdentificationMacro; - - /// Segmentation Type: (CS, 1, 1) - DcmSegTypes::E_SegmentationType m_SegmentationType; - - /// Segmentation Fractional Type: (CS, 1, 1C) (required if FRACTIONAL) - DcmSegTypes::E_SegmentationFractionalType m_SegmentationFractionalType; - - /// Maximum Fractional Value: (US, 1, 1C) (required if fractional type is FRACTIONAL) - DcmUnsignedShort m_MaximumFractionalValue; - - /// Segment descriptions from Segment Sequence - OFVector m_Segments; - - /// Multi-frame Functional Groups high level interface - FGInterface m_FGInterface; - - // --------------- private helper functions ------------------- - - /** Clear old data - */ - void clearData(); - - /** Check the length of the pixel data - * @param pixelData The Pixel Data element - * @param rows Number of rows - * @param cols Number of columns - * @param numberOfFrames Number of frames - * @result OFTrue if length is valid, OFFalse otherwise - */ - OFBool checkPixDataLength(DcmElement* pixelData, - const Uint16 rows, - const Uint16 cols, - const Uint16& numberOfFrames); - - /** Loads file - * @param dcmff The file format to load into - * @param filename The filename of the file to load - * @param dset Pointer to dataset after loading - * @return EC_Normal if loading was successful, error otherwise - */ - static OFCondition loadFile(DcmFileFormat& dcmff, - const OFString& filename, - DcmDataset*& dset); - - /** Computes the number of total bytes required for the frame data of this - * segmentation object. Takes into account dimensions and number of frames, - * as well as the type of segmentation (member variables). May file if - * size_t type is not able to hold the result of intermediate computations. - * @param rows Number of rows of a frame - * @param cols Number of cols of a frame - * @param numberOfFrames The number of frames of the object - * @param bytesRequired Will hold the result of the computation, - * if successful. Does not any padding into account. - * @return EC_Normal if computation was possible, EC_TooManyBytesRequested - * otherwise. - */ - OFCondition getTotalBytesRequired(const Uint16& rows, - const Uint16& cols, - const Uint32& numberOfFrames, - size_t& bytesRequired); - - /** Read Fractional Type of segmentation. - * @param item The item to read from - * @return EC_Normal if type could be read, EC_TagNotFound if tag is not present, - * error otherwise - */ - OFCondition readSegmentationFractionalType(DcmItem& item); - - /** Read Segmentation Type of segmentation object - * @param item The item to read from - * @return EC_Normal if type could be read, EC_TagNotFound if tag is not present, - * error otherwise - */ - OFCondition readSegmentationType(DcmItem& item); - - /** Decompress the given dataset - * @param dset The dataset to be decompressed - * @return EC_Normal if decompression worked (or dataset has already been - * decompressed), IOD_EC_CannotDecompress otherwise - */ - static OFCondition decompress(DcmDataset& dset); - + // Modules supported: + // + // Patient Module (through DcmIODImage) + // Patient Study Module (through DcmIODImage) + // General Study Module (through DcmIODImage) + // General Series Module (through DcmIODImage) + // Segmentation Series Module + // Frame of Reference Module (through DcmIODImage) + // General Equipment Module (through DcmIODImage) + // Enhanced General Equipment Module (through DcmIODImage) + // General Image Module (through DcmIODImage) + // Image Pixel Module (through DcmIODImage) + // Segmentation Image Module (through this class) + // Multi-frame Functional Group Module + // Multi-Frame Dimension Module + // SOP Common Module (through DcmIODImage) + // Common Instance Reference Module (through DcmIODImage) + + /// Segmentation Series Module + IODSegmentationSeriesModule m_SegmentationSeries; + + /// IODEnhancedEquipmentModule + IODEnhGeneralEquipmentModule m_EnhancedGeneralEquipmentModule; + + /// Multi-frame Functional Groups module + IODMultiFrameFGModule m_FG; + + /// Multi-frame Dimension Module + IODMultiframeDimensionModule m_DimensionModule; + + /// Binary frame data + OFVector m_Frames; + + /* Image level information */ + + /// Image Type: (CS, VM 2-n, Type 1), in Segmentations fixed to "DERIVED\PRIMARY" + const OFString m_ImageType; + + // Instance Number: (IS, VM 1, Type 1) + + /// Content Identification Macro + ContentIdentificationMacro m_ContentIdentificationMacro; + + /// Segmentation Type: (CS, 1, 1) + DcmSegTypes::E_SegmentationType m_SegmentationType; + + /// Segmentation Fractional Type: (CS, 1, 1C) (required if FRACTIONAL) + DcmSegTypes::E_SegmentationFractionalType m_SegmentationFractionalType; + + /// Maximum Fractional Value: (US, 1, 1C) (required if fractional type is FRACTIONAL) + DcmUnsignedShort m_MaximumFractionalValue; + + /// Segment descriptions from Segment Sequence + OFVector m_Segments; + + /// Multi-frame Functional Groups high level interface + FGInterface m_FGInterface; + + // --------------- private helper functions ------------------- + + /** Clear old data + */ + void clearData(); + + /** Check the length of the pixel data + * @param pixelData The Pixel Data element + * @param rows Number of rows + * @param cols Number of columns + * @param numberOfFrames Number of frames + * @result OFTrue if length is valid, OFFalse otherwise + */ + OFBool + checkPixDataLength(DcmElement* pixelData, const Uint16 rows, const Uint16 cols, const Uint16& numberOfFrames); + + /** Loads file + * @param dcmff The file format to load into + * @param filename The filename of the file to load + * @param dset Pointer to dataset after loading + * @return EC_Normal if loading was successful, error otherwise + */ + static OFCondition loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset); + + /** Computes the number of total bytes required for the frame data of this + * segmentation object. Takes into account dimensions and number of frames, + * as well as the type of segmentation (member variables). May file if + * size_t type is not able to hold the result of intermediate computations. + * @param rows Number of rows of a frame + * @param cols Number of cols of a frame + * @param numberOfFrames The number of frames of the object + * @param bytesRequired Will hold the result of the computation, + * if successful. Does not any padding into account. + * @return EC_Normal if computation was possible, EC_TooManyBytesRequested + * otherwise. + */ + OFCondition + getTotalBytesRequired(const Uint16& rows, const Uint16& cols, const Uint32& numberOfFrames, size_t& bytesRequired); + + /** Read Fractional Type of segmentation. + * @param item The item to read from + * @return EC_Normal if type could be read, EC_TagNotFound if tag is not present, + * error otherwise + */ + OFCondition readSegmentationFractionalType(DcmItem& item); + + /** Read Segmentation Type of segmentation object + * @param item The item to read from + * @return EC_Normal if type could be read, EC_TagNotFound if tag is not present, + * error otherwise + */ + OFCondition readSegmentationType(DcmItem& item); + + /** Decompress the given dataset + * @param dset The dataset to be decompressed + * @return EC_Normal if decompression worked (or dataset has already been + * decompressed), IOD_EC_CannotDecompress otherwise + */ + static OFCondition decompress(DcmDataset& dset); }; #endif // SEGDOC_H diff --git a/dcmseg/include/dcmtk/dcmseg/segment.h b/dcmseg/include/dcmtk/dcmseg/segment.h index f2f0d444..f7987c0c 100644 --- a/dcmseg/include/dcmtk/dcmseg/segment.h +++ b/dcmseg/include/dcmtk/dcmseg/segment.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -22,11 +22,12 @@ #ifndef SEGMENT_H #define SEGMENT_H -#include "dcmtk/config/osconfig.h" // include OS configuration first +#include "dcmtk/config/osconfig.h" // include OS configuration first + #include "dcmtk/dcmdata/dcvrus.h" #include "dcmtk/dcmiod/iodmacro.h" -#include "dcmtk/dcmseg/segtypes.h" #include "dcmtk/dcmseg/segdoc.h" +#include "dcmtk/dcmseg/segtypes.h" /** Class representing a segment from the Segment Identification Sequence, * as used within the Segmentation Image Module. It includes the Segment @@ -37,302 +38,282 @@ class DCMTK_DCMSEG_EXPORT DcmSegment { public: - - // -------------- constructors/destructors -------------------- - - // constructor is protected - - /** Destructor, frees memory - */ - virtual ~DcmSegment(); - - /** Clears all data - */ - virtual void clearData(); - - // -------------- creation -------------------- - - /** Factory method to create a Segment that expects the minimal parameters - * required. - * @param segment Pointer to the resulting segment if creation was - * successful; memory is allocated by the function - * @param segmentLabel Free text label for the segment - * @param segmentedPropertyCategory The segmented property category. - * Baseline CID 7150 “Segmentation Property Categories” should be - * used. - * @param segmentedPropertyType The segmented property type. Baseline CID - * 7151 “Segmentation Property Types” - * @param algoType The algorithm type used for segmenting this segment - * @param algoName Algorithm name (required if algoType is not MANUAL) - * @return EC_Normal if creation was successful, error otherwise - */ - static OFCondition create(DcmSegment*& segment, - const OFString& segmentLabel, - const CodeSequenceMacro& segmentedPropertyCategory, - const CodeSequenceMacro& segmentedPropertyType, - const DcmSegTypes::E_SegmentAlgoType algoType, - const OFString& algoName = ""); - - // ---------------- writing -------------------- - - /** Write segment to given item which is usually contained within - * within the Segment Sequence - * @param item The item to write to - * @return EC_Normal if successful, error otherwise - */ - OFCondition write(DcmItem& item); - - // ---------------- reading -------------------- - - /** Read segment from given item - * @param item The item to read from (must be item as found in the - * Segment Identification Sequence) - * @param clearOldData If true, old data is deleted first - * @return EC_Normal if reading was successful, error otherwise - */ - OFCondition read(DcmItem& item, - const OFBool clearOldData = OFTrue); - - // ---------------- access -------------------- - - /** Get Segment Number - * @return The Segment number - */ - virtual unsigned int getSegmentNumber(); - - /** Get Segment Label - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSegmentLabel(OFString& value, - const signed long pos = 0); - - /** Get Segment Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSegmentDescription(OFString& value, - const signed long pos = 0); - - /** Get the Segment Algorithm Type. - * @return The Algorithm Type - */ - virtual DcmSegTypes::E_SegmentAlgoType getSegmentAlgorithmType(); - - /** Get the Segment Algorithm Name - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSegmentAlgorithmName(OFString& value, - const signed long pos = 0); - - /** Get General Anatomy Code - * @return Reference to the General Anatomy Macro, may be unset - */ - virtual GeneralAnatomyMacro& getGeneralAnatomyCode(); - - /** Get Segmented Property Category Code - * @return Reference to the Segmented Property Category Code, may be unset - */ - virtual CodeSequenceMacro& getSegmentedPropertyCategoryCode(); - - /** Get Segmented Property Type Code - * @return Reference to the Segmented Property Type Code, may be unset - */ - virtual CodeSequenceMacro& getSegmentedPropertyTypeCode(); - - /** Get Segmented Property Type Modifier Code - * @return Reference to the Segmented Property Type Modifier Code, may - * be unset - */ - virtual OFVector& getSegmentedPropertyTypeModifierCode(); - - /** Get Segmentation Algorithm Identification - * @warning This method has earlier been named getSegmentSurfaceGenerationAlgorithmIdentification() - * which has changed due to DICOM CP-1597. The code value returned is now - * taken from the "Segmentation Algorithm Identification Sequence" instead of the - * "Segment Surface Generation Algorithm Identification Sequence". - * @return Reference to the Segmentation Algorithm Identification - * Identification, may be unset - */ - virtual AlgorithmIdentificationMacro& getSegmentationAlgorithmIdentification(); - - /** Get Recommended Display Grayscale Value - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1) - * @return EC_Normal if successful, an error code otherwise - */ virtual OFCondition getRecommendedDisplayGrayscaleValue(Uint16& value, - const unsigned long pos = 0); - - /** Returns Recommended Display CIELab Value - * @param L The L component - * @param a The a* component - * @param b The b* component - * @return EC_Normal if values could be returned - */ - virtual OFCondition getRecommendedDisplayCIELabValue(Uint16& L, - Uint16& a, - Uint16& b); - - /** Get Tracking ID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTrackingID(OFString& value, - const signed long pos = 0); - - /** Get Tracking UID - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getTrackingUID(OFString& value, - const signed long pos = 0); - - - // -------------- setters -------------------- - - /** Set Segment Label - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSegmentLabel(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Segment Label - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (ST) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSegmentDescription(const OFString& value, + // -------------- constructors/destructors -------------------- + + // constructor is protected + + /** Destructor, frees memory + */ + virtual ~DcmSegment(); + + /** Clears all data + */ + virtual void clearData(); + + // -------------- creation -------------------- + + /** Factory method to create a Segment that expects the minimal parameters + * required. + * @param segment Pointer to the resulting segment if creation was + * successful; memory is allocated by the function + * @param segmentLabel Free text label for the segment + * @param segmentedPropertyCategory The segmented property category. + * Baseline CID 7150 “Segmentation Property Categories” should be + * used. + * @param segmentedPropertyType The segmented property type. Baseline CID + * 7151 “Segmentation Property Types” + * @param algoType The algorithm type used for segmenting this segment + * @param algoName Algorithm name (required if algoType is not MANUAL) + * @return EC_Normal if creation was successful, error otherwise + */ + static OFCondition create(DcmSegment*& segment, + const OFString& segmentLabel, + const CodeSequenceMacro& segmentedPropertyCategory, + const CodeSequenceMacro& segmentedPropertyType, + const DcmSegTypes::E_SegmentAlgoType algoType, + const OFString& algoName = ""); + + // ---------------- writing -------------------- + + /** Write segment to given item which is usually contained within + * within the Segment Sequence + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + OFCondition write(DcmItem& item); + + // ---------------- reading -------------------- + + /** Read segment from given item + * @param item The item to read from (must be item as found in the + * Segment Identification Sequence) + * @param clearOldData If true, old data is deleted first + * @return EC_Normal if reading was successful, error otherwise + */ + OFCondition read(DcmItem& item, const OFBool clearOldData = OFTrue); + + // ---------------- access -------------------- + + /** Get Segment Number + * @return The Segment number + */ + virtual unsigned int getSegmentNumber(); + + /** Get Segment Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSegmentLabel(OFString& value, const signed long pos = 0); + + /** Get Segment Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSegmentDescription(OFString& value, const signed long pos = 0); + + /** Get the Segment Algorithm Type. + * @return The Algorithm Type + */ + virtual DcmSegTypes::E_SegmentAlgoType getSegmentAlgorithmType(); + + /** Get the Segment Algorithm Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSegmentAlgorithmName(OFString& value, const signed long pos = 0); + + /** Get General Anatomy Code + * @return Reference to the General Anatomy Macro, may be unset + */ + virtual GeneralAnatomyMacro& getGeneralAnatomyCode(); + + /** Get Segmented Property Category Code + * @return Reference to the Segmented Property Category Code, may be unset + */ + virtual CodeSequenceMacro& getSegmentedPropertyCategoryCode(); + + /** Get Segmented Property Type Code + * @return Reference to the Segmented Property Type Code, may be unset + */ + virtual CodeSequenceMacro& getSegmentedPropertyTypeCode(); + + /** Get Segmented Property Type Modifier Code + * @return Reference to the Segmented Property Type Modifier Code, may + * be unset + */ + virtual OFVector& getSegmentedPropertyTypeModifierCode(); + + /** Get Segmentation Algorithm Identification + * @warning This method has earlier been named getSegmentSurfaceGenerationAlgorithmIdentification() + * which has changed due to DICOM CP-1597. The code value returned is now + * taken from the "Segmentation Algorithm Identification Sequence" instead of the + * "Segment Surface Generation Algorithm Identification Sequence". + * @return Reference to the Segmentation Algorithm Identification + * Identification, may be unset + */ + virtual AlgorithmIdentificationMacro& getSegmentationAlgorithmIdentification(); + + /** Get Recommended Display Grayscale Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRecommendedDisplayGrayscaleValue(Uint16& value, const unsigned long pos = 0); + + /** Returns Recommended Display CIELab Value + * @param L The L component + * @param a The a* component + * @param b The b* component + * @return EC_Normal if values could be returned + */ + virtual OFCondition getRecommendedDisplayCIELabValue(Uint16& L, Uint16& a, Uint16& b); + + /** Get Tracking ID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTrackingID(OFString& value, const signed long pos = 0); + + /** Get Tracking UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTrackingUID(OFString& value, const signed long pos = 0); + + // -------------- setters -------------------- + + /** Set Segment Label + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSegmentLabel(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Segment Label + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (ST) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSegmentDescription(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Segment Algorithm + * @param algoType Algorithm type used to find segment + * @param algoName Name of the algorithm used (required if algorithm type + * is not MANUAL + * @param checkValue If OFTrue, input is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setSegmentAlgorithm(const DcmSegTypes::E_SegmentAlgoType algoType, + const OFString& algoName, const OFBool checkValue = OFTrue); - /** Set Segment Algorithm - * @param algoType Algorithm type used to find segment - * @param algoName Name of the algorithm used (required if algorithm type - * is not MANUAL - * @param checkValue If OFTrue, input is checked for validity - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setSegmentAlgorithm(const DcmSegTypes::E_SegmentAlgoType algoType, - const OFString& algoName, - const OFBool checkValue = OFTrue); - - /** Set Segmentation Algorithm Identification - * @warning This method has earlier been named setSegmentSurfaceGenerationAlgorithmIdentification() - * which has changed due to DICOM CP-1597. The resulting code value is now - * written to the "Segmentation Algorithm Identification Sequence" instead of the - * "Segment Surface Generation Algorithm Identification Sequence". - * @param value The algorithm identification - * @param checkValue If OFTrue, value undergoes some validity checks - * @return EC_Normal if setting was successful, error otherwise - */ - virtual OFCondition setSegmentationAlgorithmIdentification(const AlgorithmIdentificationMacro& value, - const OFBool checkValue = OFTrue); - - /** Set Recommended Display Grayscale Value - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for validity if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRecommendedDisplayGrayscaleValue(const Uint16 value, - const OFBool checkValue = OFTrue); - - /** Set Recommended Display CIELab Value - * @param L L component - * @param a a component - * @param b b component - * @param checkValue Check 'value' for validity if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setRecommendedDisplayCIELabValue(const Uint16 L, - const Uint16 a, - const Uint16 b, - const OFBool checkValue = OFTrue); - - /** Set Tracking ID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setTrackingID(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Tracking UID - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setTrackingUID(const OFString& value, - const OFBool checkValue = OFTrue); - - /// The utility class must access the protected default constructor - friend class DcmIODUtil; + /** Set Segmentation Algorithm Identification + * @warning This method has earlier been named setSegmentSurfaceGenerationAlgorithmIdentification() + * which has changed due to DICOM CP-1597. The resulting code value is now + * written to the "Segmentation Algorithm Identification Sequence" instead of the + * "Segment Surface Generation Algorithm Identification Sequence". + * @param value The algorithm identification + * @param checkValue If OFTrue, value undergoes some validity checks + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setSegmentationAlgorithmIdentification(const AlgorithmIdentificationMacro& value, + const OFBool checkValue = OFTrue); + + /** Set Recommended Display Grayscale Value + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for validity if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRecommendedDisplayGrayscaleValue(const Uint16 value, const OFBool checkValue = OFTrue); + + /** Set Recommended Display CIELab Value + * @param L L component + * @param a a component + * @param b b component + * @param checkValue Check 'value' for validity if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition + setRecommendedDisplayCIELabValue(const Uint16 L, const Uint16 a, const Uint16 b, const OFBool checkValue = OFTrue); + + /** Set Tracking ID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTrackingID(const OFString& value, const OFBool checkValue = OFTrue); + + /** Set Tracking UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTrackingUID(const OFString& value, const OFBool checkValue = OFTrue); + + /// The utility class must access the protected default constructor + friend class DcmIODUtil; protected: + /** Protected default constructor + */ + DcmSegment(); - /** Protected default constructor - */ - DcmSegment(); - - /** Initialize IOD rules for this component - */ - virtual void initIODRules(); - - /** Set reference to the Segmentation object that this segment belongs to. - * This is used to find the Segment Number this Segment has within the - * Segmentation. - * @param doc Pointer to the Segmentation object - */ - void referenceSegmentationDoc(DcmSegmentation* doc); + /** Initialize IOD rules for this component + */ + virtual void initIODRules(); + /** Set reference to the Segmentation object that this segment belongs to. + * This is used to find the Segment Number this Segment has within the + * Segmentation. + * @param doc Pointer to the Segmentation object + */ + void referenceSegmentationDoc(DcmSegmentation* doc); private: + /** Private undefined copy constructor + */ + DcmSegment(const DcmSegment&); - /** Private undefined copy constructor - */ - DcmSegment(const DcmSegment&); - - /** Private undefined assignment operator - * @return Reference to "this" class - */ - DcmSegment& operator=(const DcmSegment&); + /** Private undefined assignment operator + * @return Reference to "this" class + */ + DcmSegment& operator=(const DcmSegment&); - /// The segmentation document where this segment is located in - DcmSegmentation* m_SegmentationDoc; + /// The segmentation document where this segment is located in + DcmSegmentation* m_SegmentationDoc; - /// Segment Description Macro - SegmentDescriptionMacro m_SegmentDescription; + /// Segment Description Macro + SegmentDescriptionMacro m_SegmentDescription; - /// Segment Algorithm Name: (LO, 1, 1C) - DcmLongString m_SegmentAlgorithmName; + /// Segment Algorithm Name: (LO, 1, 1C) + DcmLongString m_SegmentAlgorithmName; - /// Segmentation Algorithm Identification (SQ, 1, 3). - /// This attribute has earlier been named m_SegmentationSurfaceGenerationAlgorithmIdentification - /// representing the related sequence. This has been changed in favor of the - /// Segmentation Algorithm Identification Sequence due to DICOM CP-1597. - AlgorithmIdentificationMacro m_SegmentationAlgorithmIdentification; + /// Segmentation Algorithm Identification (SQ, 1, 3). + /// This attribute has earlier been named m_SegmentationSurfaceGenerationAlgorithmIdentification + /// representing the related sequence. This has been changed in favor of the + /// Segmentation Algorithm Identification Sequence due to DICOM CP-1597. + AlgorithmIdentificationMacro m_SegmentationAlgorithmIdentification; - /// Recommended Display Grayscale Value (US, 1, 3) - DcmUnsignedShort m_RecommendedDisplayGrayscaleValue; + /// Recommended Display Grayscale Value (US, 1, 3) + DcmUnsignedShort m_RecommendedDisplayGrayscaleValue; - /// Recommended Display CIELab Value (US, 3, 3) - DcmUnsignedShort m_RecommendedDisplayCIELabValue; + /// Recommended Display CIELab Value (US, 3, 3) + DcmUnsignedShort m_RecommendedDisplayCIELabValue; - /// Tracking ID (UT, 1, 1C) - DcmUnlimitedText m_TrackingID; + /// Tracking ID (UT, 1, 1C) + DcmUnlimitedText m_TrackingID; - /// Tracking UID (UI, 1, 1C) - DcmUniqueIdentifier m_TrackingUID; + /// Tracking UID (UI, 1, 1C) + DcmUniqueIdentifier m_TrackingUID; - /// Rules for data elements within this IOD - IODRules m_Rules; + /// Rules for data elements within this IOD + IODRules m_Rules; }; #endif // SEGMENT_H diff --git a/dcmseg/include/dcmtk/dcmseg/segtypes.h b/dcmseg/include/dcmtk/dcmseg/segtypes.h index 283beb4d..450831e8 100644 --- a/dcmseg/include/dcmtk/dcmseg/segtypes.h +++ b/dcmseg/include/dcmtk/dcmseg/segtypes.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2020, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,21 +23,21 @@ #define SEGTYPES_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/oflog/oflog.h" + #include "dcmtk/dcmiod/iodmacro.h" #include "dcmtk/dcmseg/segdef.h" +#include "dcmtk/oflog/oflog.h" /* * * Logging */ -extern OFString c; extern DCMTK_DCMSEG_EXPORT OFLogger DCM_dcmsegLogger; #define DCMSEG_TRACE(msg) OFLOG_TRACE(DCM_dcmsegLogger, msg) #define DCMSEG_DEBUG(msg) OFLOG_DEBUG(DCM_dcmsegLogger, msg) -#define DCMSEG_INFO(msg) OFLOG_INFO(DCM_dcmsegLogger, msg) -#define DCMSEG_WARN(msg) OFLOG_WARN(DCM_dcmsegLogger, msg) +#define DCMSEG_INFO(msg) OFLOG_INFO(DCM_dcmsegLogger, msg) +#define DCMSEG_WARN(msg) OFLOG_WARN(DCM_dcmsegLogger, msg) #define DCMSEG_ERROR(msg) OFLOG_ERROR(DCM_dcmsegLogger, msg) #define DCMSEG_FATAL(msg) OFLOG_FATAL(DCM_dcmsegLogger, msg) @@ -64,15 +64,15 @@ const Uint32 DCM_SEG_MAX_SEGMENTS = 65535; //@{ /// error: specified functional group is already existing -extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_MaxSegmentsReached; +extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_MaxSegmentsReached; /// error: specified segment does not exist -extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NoSuchSegment; +extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NoSuchSegment; /// error: unknown segmentation type -extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_UnknownSegmentationType; +extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_UnknownSegmentationType; /// error: invalid value -extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_InvalidValue; +extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_InvalidValue; /// error: not enough data -extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NotEnoughData; +extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NotEnoughData; /** General purpose class hiding global functions, constants and types in the * segmentation context from the global namespace. @@ -80,57 +80,54 @@ extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NotEnoughData; class DCMTK_DCMSEG_EXPORT DcmSegTypes { - public: - - /** Segmentation object types +public: + /** Segmentation object types */ enum E_SegmentationType { - /// Unknown (e.g.\ not initialized) - ST_UNKNOWN, - /// Binary segmentation with 1 bit depth denoting whether a pixel - /// belongs to a segmentation or not. - ST_BINARY, - /// Fractional segmentation where fraction specifies how much of voxel - /// is occupied by the segment - ST_FRACTIONAL + /// Unknown (e.g.\ not initialized) + ST_UNKNOWN, + /// Binary segmentation with 1 bit depth denoting whether a pixel + /// belongs to a segmentation or not. + ST_BINARY, + /// Fractional segmentation where fraction specifies how much of voxel + /// is occupied by the segment + ST_FRACTIONAL }; /** Segment Algorithm Type */ enum E_SegmentAlgoType { - /// Unknown (e.g.\ not initialized) - SAT_UNKNOWN, - /// Calculated segment - SAT_AUTOMATIC, - /// Calculated segment with user interaction - SAT_SEMIAUTOMATIC, - /// Manual segment creation - SAT_MANUAL + /// Unknown (e.g.\ not initialized) + SAT_UNKNOWN, + /// Calculated segment + SAT_AUTOMATIC, + /// Calculated segment with user interaction + SAT_SEMIAUTOMATIC, + /// Manual segment creation + SAT_MANUAL }; - /** Segmentation object Fractional Type */ enum E_SegmentationFractionalType { - /// Unknown (e.g.\ not initialized) - SFT_UNKNOWN, - /// For fractional segmentations, a value defines probability that pixel belongs to segment - SFT_PROBABILITY, - /// For fractional segmentations, a value defines how much of the pixel is covered by the segment - SFT_OCCUPANCY + /// Unknown (e.g.\ not initialized) + SFT_UNKNOWN, + /// For fractional segmentations, a value defines probability that pixel belongs to segment + SFT_PROBABILITY, + /// For fractional segmentations, a value defines how much of the pixel is covered by the segment + SFT_OCCUPANCY }; - // -- helper functions -- /** Return string representation of algorithm type * @param algo The algorithm type * @return The algorithm type as a string */ - static OFString algoType2OFString(E_SegmentAlgoType algo ); + static OFString algoType2OFString(E_SegmentAlgoType algo); /** Return enum representation of algorithm type string as found in * segmentation objects @@ -144,20 +141,20 @@ class DCMTK_DCMSEG_EXPORT DcmSegTypes * @param value The segmentation type as a string * @return The segmentation type as enum value */ - static DcmSegTypes::E_SegmentationType OFString2Segtype( const OFString& value ); + static DcmSegTypes::E_SegmentationType OFString2Segtype(const OFString& value); /** Return string representation from segmentation enum type * @param value The segmentation type as enum value * @return The segmentation type as a string */ - static OFString segtype2OFString( const DcmSegTypes::E_SegmentationType& value ); + static OFString segtype2OFString(const DcmSegTypes::E_SegmentationType& value); /** Return enum representation of fractional type string as found in * segmentation objects * @param value The fractional type as a string * @return The fractional type as enum value */ - static DcmSegTypes::E_SegmentationFractionalType OFString2FractionalType( const OFString& value ); + static DcmSegTypes::E_SegmentationFractionalType OFString2FractionalType(const OFString& value); }; /** Class representing the Segmented Property Type Code and Segmented @@ -167,60 +164,56 @@ class DCMTK_DCMSEG_EXPORT SegmentedPropertyTypeCodeItem { public: + /// Easy access to containing class + friend class SegmentDescriptionMacro; - /// Easy access to containing class - friend class SegmentDescriptionMacro; - - /** Constructor - */ - SegmentedPropertyTypeCodeItem(); - - /** Virtual destructor, frees memory - */ - virtual ~SegmentedPropertyTypeCodeItem(); - - /** Clear all data - */ - virtual void clearData(); - - /** Check whether class has valid data - * @param quiet If OFTrue, check will not produce any warnings or errors - * on the logger. Default is OFFalse. - * @return EC_Normal if data is valid, error otherwise - */ - virtual OFCondition check(const OFBool quiet = OFFalse); - - /** Read data from given item - * @param item The item to read from - * @param clearOldData If OFTrue, old data is cleared before reading - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item, - const OFBool clearOldData = OFTrue); - - /** Write data to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); + /** Constructor + */ + SegmentedPropertyTypeCodeItem(); -protected: + /** Virtual destructor, frees memory + */ + virtual ~SegmentedPropertyTypeCodeItem(); - /** Check whether the modifier codes are ok - * @param quiet If OFTrue, no warnings or errors will be printed to the - * loggers. Default is OFFalse. - * @return EC_Normal if data is ok, error otherwise - */ - OFCondition checkModifiers(const OFBool quiet = OFFalse); + /** Clear all data + */ + virtual void clearData(); -private: + /** Check whether class has valid data + * @param quiet If OFTrue, check will not produce any warnings or errors + * on the logger. Default is OFFalse. + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); - /// Segmented Property Type Code (SQ,1,1) - /// Baseline CID 7151 - CodeSequenceMacro m_SegmentedPropertyTypeCode; + /** Read data from given item + * @param item The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item, const OFBool clearOldData = OFTrue); + + /** Write data to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); - /// Segmented Property Type Modifier Code (SQ, VM 1-n, Type 3) - OFVector m_SegmentedPropertyTypeModifierCode; +protected: + /** Check whether the modifier codes are ok + * @param quiet If OFTrue, no warnings or errors will be printed to the + * loggers. Default is OFFalse. + * @return EC_Normal if data is ok, error otherwise + */ + OFCondition checkModifiers(const OFBool quiet = OFFalse); + +private: + /// Segmented Property Type Code (SQ,1,1) + /// Baseline CID 7151 + CodeSequenceMacro m_SegmentedPropertyTypeCode; + + /// Segmented Property Type Modifier Code (SQ, VM 1-n, Type 3) + OFVector m_SegmentedPropertyTypeModifierCode; }; /** Class representing the Segment Description Macro @@ -229,135 +222,125 @@ class DCMTK_DCMSEG_EXPORT SegmentDescriptionMacro { public: + /** Constructor + */ + SegmentDescriptionMacro(); + + /** Virtual destructor, frees memory + */ + virtual ~SegmentDescriptionMacro(); - /** Constructor - */ - SegmentDescriptionMacro(); - - /** Virtual destructor, frees memory - */ - virtual ~SegmentDescriptionMacro(); - - /** Clear all data - */ - virtual void clearData(); - - /** Read class data from given item - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition read(DcmItem& item); - - /** Writes the data from this class to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition write(DcmItem& item); - - /** Get Segment Label - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSegmentLabel(OFString& value, - const signed long pos = 0); - - /** Get Segment Description - * @param value Reference to variable in which the value should be stored - * @param pos Index of the value to get (0..vm-1), -1 for all components - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition getSegmentDescription(OFString& value, - const signed long pos = 0); - - /** Get Segment Algorithm Type - * @return The algorithm type - */ - virtual DcmSegTypes::E_SegmentAlgoType getSegmentAlgorithmType(); - - /** Get reference to General Anatomy Code - * @return Reference to General Anatomy Code - */ - virtual GeneralAnatomyMacro& getGeneralAnatomyCode(); - - /** Get Reference to Segmented Property Category Code - * @return Reference to Segmented Property Category Code - */ - virtual CodeSequenceMacro& getSegmentedPropertyCategoryCode(); - - /** Get Reference to Segmented Property Type Code - * @return Reference to Segmented Property Type Code - */ - virtual CodeSequenceMacro& getSegmentedPropertyTypeCode(); - - /** Get Reference to Segmented Property Type Modifier Codes - * @return Reference to Segmented Property Type Modifier Codes - */ - virtual OFVector& getSegmentedPropertyTypeModifier(); - - /** Set Segment Label - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) - * if enabled - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSegmentLabel(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Segment Description - * @param value Value to be set (single value only) or "" for no value - * @param checkValue Check 'value'. Not evaluated (here for consistency - * with other setter functions). - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSegmentDescription(const OFString& value, - const OFBool checkValue = OFTrue); - - /** Set Segment Algorithm Type - * @param value Value to be set - * @return EC_Normal if successful, an error code otherwise - */ - virtual OFCondition setSegmentAlgorithmType(const DcmSegTypes::E_SegmentAlgoType value); + /** Clear all data + */ + virtual void clearData(); -protected: + /** Read class data from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); - /** Read Segment Algorithm Type from given item - * @param item The item to read from - * @return EC_Normal if reading was successful, error otherwise - */ - virtual OFCondition readSegmentAlgorithmType(DcmItem& item); + /** Writes the data from this class to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); - /** Write Segment Algorithm Type to given item - * @param item The item to write to - * @return EC_Normal if writing was successful, error otherwise - */ - virtual OFCondition writeSegmentAlgorithmType(DcmItem& item); + /** Get Segment Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSegmentLabel(OFString& value, const signed long pos = 0); + /** Get Segment Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSegmentDescription(OFString& value, const signed long pos = 0); -private: + /** Get Segment Algorithm Type + * @return The algorithm type + */ + virtual DcmSegTypes::E_SegmentAlgoType getSegmentAlgorithmType(); - // Segment Number: (US, VM 1, Type 1): Computed by position in vector of DcmSegmentation - // DcmUnsignedShort m_SegmentNumber; - /// Segment Number: (LO, VM 1, Type 1) - DcmLongString m_SegmentLabel; + /** Get reference to General Anatomy Code + * @return Reference to General Anatomy Code + */ + virtual GeneralAnatomyMacro& getGeneralAnatomyCode(); - /// Segment Description: (ST, 1, Type 3) - DcmShortText m_SegmentDescription; + /** Get Reference to Segmented Property Category Code + * @return Reference to Segmented Property Category Code + */ + virtual CodeSequenceMacro& getSegmentedPropertyCategoryCode(); - /// Segment Algorithm Type: (CS, 1, Type 1) - DcmSegTypes::E_SegmentAlgoType m_SegmentAlgorithmType; + /** Get Reference to Segmented Property Type Code + * @return Reference to Segmented Property Type Code + */ + virtual CodeSequenceMacro& getSegmentedPropertyTypeCode(); - /// General Anatomy Mandatory Macro - GeneralAnatomyMacro m_GeneralAnatomyCode; + /** Get Reference to Segmented Property Type Modifier Codes + * @return Reference to Segmented Property Type Modifier Codes + */ + virtual OFVector& getSegmentedPropertyTypeModifier(); - /// Segment Property Category Code (SQ, 1, 1) - /// Baseline CID 7150 - CodeSequenceMacro m_SegmentedPropertyCategoryCode; + /** Set Segment Label + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSegmentLabel(const OFString& value, const OFBool checkValue = OFTrue); - /// Segmented Property Type Code - SegmentedPropertyTypeCodeItem m_SegmentedPropertyType; + /** Set Segment Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value'. Not evaluated (here for consistency + * with other setter functions). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSegmentDescription(const OFString& value, const OFBool checkValue = OFTrue); -}; + /** Set Segment Algorithm Type + * @param value Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSegmentAlgorithmType(const DcmSegTypes::E_SegmentAlgoType value); + +protected: + /** Read Segment Algorithm Type from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSegmentAlgorithmType(DcmItem& item); + /** Write Segment Algorithm Type to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeSegmentAlgorithmType(DcmItem& item); + +private: + // Segment Number: (US, VM 1, Type 1): Computed by position in vector of DcmSegmentation + // DcmUnsignedShort m_SegmentNumber; + /// Segment Number: (LO, VM 1, Type 1) + DcmLongString m_SegmentLabel; + + /// Segment Description: (ST, 1, Type 3) + DcmShortText m_SegmentDescription; + + /// Segment Algorithm Type: (CS, 1, Type 1) + DcmSegTypes::E_SegmentAlgoType m_SegmentAlgorithmType; + + /// General Anatomy Mandatory Macro + GeneralAnatomyMacro m_GeneralAnatomyCode; + + /// Segment Property Category Code (SQ, 1, 1) + /// Baseline CID 7150 + CodeSequenceMacro m_SegmentedPropertyCategoryCode; + + /// Segmented Property Type Code + SegmentedPropertyTypeCodeItem m_SegmentedPropertyType; +}; #endif // SEGTYPES_H diff --git a/dcmseg/include/dcmtk/dcmseg/segutils.h b/dcmseg/include/dcmtk/dcmseg/segutils.h index 91d4cde1..02571a0c 100644 --- a/dcmseg/include/dcmtk/dcmseg/segutils.h +++ b/dcmseg/include/dcmtk/dcmseg/segutils.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -23,6 +23,7 @@ #define SEGUTILS_H #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmseg/segdef.h" #include "dcmtk/dcmseg/segtypes.h" @@ -32,104 +33,93 @@ class DCMTK_DCMSEG_EXPORT DcmSegUtils { public: + /** Pack the given segmentation pixel data, provided "unpacked", into + * the packed format expected by DICOM + * @param pixelData Pixel data in unpacked format + * @param rows Number of rows in the pixel data + * @param columns The number of columns in the pixel data + * @return The frame data if successful, NULL if an error occurs + */ + static DcmIODTypes::Frame* packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns); - /** Pack the given segmentation pixel data, provided "unpacked", into - * the packed format expected by DICOM - * @param pixelData Pixel data in unpacked format - * @param rows Number of rows in the pixel data - * @param columns The number of columns in the pixel data - * @return The frame data if successful, NULL if an error occurs - */ - static DcmIODTypes::Frame* packBinaryFrame(const Uint8* pixelData, - const Uint16 rows, - const Uint16 columns); - - /** Compute the number of bytes required for a binary pixel data frame, - * given the number of pixels - * @param numPixels The total number of pixels - * @return The number of bytes required to pack the data into a binary - * segmentation frame - */ - static size_t getBytesForBinaryFrame(const size_t& numPixels); + /** Compute the number of bytes required for a binary pixel data frame, + * given the number of pixels + * @param numPixels The total number of pixels + * @return The number of bytes required to pack the data into a binary + * segmentation frame + */ + static size_t getBytesForBinaryFrame(const size_t& numPixels); - /** Unpacks a binary segmentation frame into a "sparse" pixel data frame where - * every resulting byte represents a single bit of the frame being either - * 0 (not set) or 1 (set). - * @param frame The input buffer with the frame in packed format - * @param rows The rows of the frame - * @param cols The cols of the frame - * @return The segmentation frame in unpacked format. NULL in case of error. - */ - static DcmIODTypes::Frame* unpackBinaryFrame(const DcmIODTypes::Frame* frame, - Uint16 rows, - Uint16 cols); + /** Unpacks a binary segmentation frame into a "sparse" pixel data frame where + * every resulting byte represents a single bit of the frame being either + * 0 (not set) or 1 (set). + * @param frame The input buffer with the frame in packed format + * @param rows The rows of the frame + * @param cols The cols of the frame + * @return The segmentation frame in unpacked format. NULL in case of error. + */ + static DcmIODTypes::Frame* unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols); - /** Aligns 1 bit per pixel frame data to make the frame start at a - * specific bit position within the first byte. This is used in the context - * that dcmseg holds the frames in memory aligned to exact byte positions, - * while the DICOM encoding might require a frame to start at an arbitrary - * bit position since all (1 bit per pixel) frames are directly concatenated - * one after another (i.e. if one frame does not occupy a number of bits - * dividable by 8, not all frames will be aligned at exact byte positions). - * Note that each byte is filled from the right, i.e. the first pixel will - * represented by the bit at the very right of the first byte, and the 9th - * pixel will be in the very right position of the following byte. - * This is not a regular bit shift operation since the bits from the previous - * frame are on the left of the byte, but must be aligned at the right. The - * current frame starts from the first bit, occupying the unused bits of - * the last frame and then continuing in the next byte at the first bit - * from the left. - * Example for two bit shift: - * Input buffer bytes: hgfedcba 87654321 - * Result: fedcba00 654321hg - * The 00 in the first byte must be handled by the caller (will - * contain the two bits of the previous frame). - * See also dcmseg/tests/tutils.cc for more examples. - * @param buf The address of the memory buffer to shift - * @param bufLen The length of the buf memory block in bytes - * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. - */ - static void alignFrameOnBitPosition(Uint8* buf, - size_t bufLen, - Uint8 numBits); + /** Aligns 1 bit per pixel frame data to make the frame start at a + * specific bit position within the first byte. This is used in the context + * that dcmseg holds the frames in memory aligned to exact byte positions, + * while the DICOM encoding might require a frame to start at an arbitrary + * bit position since all (1 bit per pixel) frames are directly concatenated + * one after another (i.e. if one frame does not occupy a number of bits + * dividable by 8, not all frames will be aligned at exact byte positions). + * Note that each byte is filled from the right, i.e. the first pixel will + * represented by the bit at the very right of the first byte, and the 9th + * pixel will be in the very right position of the following byte. + * This is not a regular bit shift operation since the bits from the previous + * frame are on the left of the byte, but must be aligned at the right. The + * current frame starts from the first bit, occupying the unused bits of + * the last frame and then continuing in the next byte at the first bit + * from the left. + * Example for two bit shift: + * Input buffer bytes: hgfedcba 87654321 + * Result: fedcba00 654321hg + * The 00 in the first byte must be handled by the caller (will + * contain the two bits of the previous frame). + * See also dcmseg/tests/tutils.cc for more examples. + * @param buf The address of the memory buffer to shift + * @param bufLen The length of the buf memory block in bytes + * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. + */ + static void alignFrameOnBitPosition(Uint8* buf, const size_t bufLen, const Uint8 numBits); - /** Aligns 1 bit per pixel frame data starting at a given bit position in the - * provided buffer with the start of that buffer. This is used to create - * a frame structure where all the bytes (including the first one) only - * contain data from the frame at hand. - * Note that each byte is filled from the right, i.e. the first pixel will - * represented by the bit at the very right of the first byte, and the 9th - * pixel will be in the very right position of the following byte. - * Example: - * 3 bytes input buffer: edcbaZYX mlkjihgf utsrqpon - * Result after aligning 3 bits: fghedcba ponmlkji 000utsrq - * The 000 are unused bits and therefore zeroed out in the last byte. Bits - * ZYX will be shifted out which is ok since it does not belong to the - * current frame. See also dcmseg/tests/tutils.cc for more examples. - * @param buf The address of the memory buffer to shift - * @param bufLen The length of the buf memory block in bytes - * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. - */ - static void alignFrameOnByteBoundary(Uint8* buf, - size_t bufLen, - Uint8 numBits); + /** Aligns 1 bit per pixel frame data starting at a given bit position in the + * provided buffer with the start of that buffer. This is used to create + * a frame structure where all the bytes (including the first one) only + * contain data from the frame at hand. + * Note that each byte is filled from the right, i.e. the first pixel will + * represented by the bit at the very right of the first byte, and the 9th + * pixel will be in the very right position of the following byte. + * Example: + * 3 bytes input buffer: edcbaZYX mlkjihgf utsrqpon + * Result after aligning 3 bits: fghedcba ponmlkji 000utsrq + * The 000 are unused bits and therefore zeroed out in the last byte. Bits + * ZYX will be shifted out which is ok since it does not belong to the + * current frame. See also dcmseg/tests/tutils.cc for more examples. + * @param buf The address of the memory buffer to shift + * @param bufLen The length of the buf memory block in bytes + * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. + */ + static void alignFrameOnByteBoundary(Uint8* buf, const size_t bufLen, const Uint8 numBits); - /** Dumps a byte as binary number to a string. Only useful for - * debugging purposes. - * @param b The byte to dump - * @return A string containing b as a binary number - */ - static OFString debugByte2Bin(Uint8 b); + /** Dumps a byte as binary number to a string. Only useful for + * debugging purposes. + * @param b The byte to dump + * @return A string containing b as a binary number + */ + static OFString debugByte2Bin(Uint8 b); - /** Dumps a memory block byte for byte to the debug log stream. Only useful - * for debugging purposes. - * @param buffer The address of the memory block to dump - * @param length The length of memory to be dumped - * @param what String describing what is dumped. - */ - static void debugDumpBin(Uint8* buffer, - size_t length, - const char* what); + /** Dumps a memory block byte for byte to the debug log stream. Only useful + * for debugging purposes. + * @param buffer The address of the memory block to dump + * @param length The length of memory to be dumped + * @param what String describing what is dumped. + */ + static void debugDumpBin(Uint8* buffer, size_t length, const char* what); }; #endif // SEGUTILS_H diff --git a/dcmseg/libsrc/Makefile.dep b/dcmseg/libsrc/Makefile.dep index c3e4e7b1..23061616 100644 --- a/dcmseg/libsrc/Makefile.dep +++ b/dcmseg/libsrc/Makefile.dep @@ -7,40 +7,25 @@ segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../include/dcmtk/dcmseg/segdoc.h \ - ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ - ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ - ../../ofstd/include/dcmtk/ofstd/diag/push.def \ - ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ - ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ - ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ - ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ ../../oflog/include/dcmtk/oflog/config/defines.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ @@ -51,13 +36,9 @@ segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ @@ -65,10 +46,12 @@ segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ @@ -85,6 +68,7 @@ segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -129,43 +113,66 @@ segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ - ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgderimg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgfact.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../include/dcmtk/dcmseg/segdoc.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ - ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ - ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ - ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ - ../../dcmfg/include/dcmtk/dcmfg/fg.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ - ../include/dcmtk/dcmseg/segtypes.h ../include/dcmtk/dcmseg/segdef.h \ - ../include/dcmtk/dcmseg/segment.h ../include/dcmtk/dcmseg/segutils.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgfact.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgderimg.h + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \ + ../include/dcmtk/dcmseg/segment.h ../include/dcmtk/dcmseg/segutils.h segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ @@ -173,14 +180,13 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -206,32 +212,31 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../include/dcmtk/dcmseg/segment.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmseg/segdoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ @@ -249,7 +254,6 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ @@ -259,7 +263,6 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ @@ -275,6 +278,7 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ @@ -285,44 +289,50 @@ segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ - ../include/dcmtk/dcmseg/segtypes.h ../include/dcmtk/dcmseg/segdef.h \ - ../include/dcmtk/dcmseg/segdoc.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ - ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ - ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ - ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ ../../ofstd/include/dcmtk/ofstd/diag/push.def \ - ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ - ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ - ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ - ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ - ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ - ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ - ../../dcmfg/include/dcmtk/dcmfg/fg.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ - ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \ + ../include/dcmtk/dcmseg/segment.h segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ @@ -334,13 +344,8 @@ segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -355,6 +360,7 @@ segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -366,42 +372,38 @@ segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -412,9 +414,11 @@ segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -444,15 +448,33 @@ segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ ../include/dcmtk/dcmseg/segtypes.h ../include/dcmtk/dcmseg/segdef.h segutils.o: segutils.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/dcmseg/segutils.h ../include/dcmtk/dcmseg/segdef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ - ../include/dcmtk/dcmseg/segtypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -460,16 +482,12 @@ segutils.o: segutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ ../../oflog/include/dcmtk/oflog/loglevel.h \ ../../ofstd/include/dcmtk/ofstd/ofvector.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ - ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../oflog/include/dcmtk/oflog/tstring.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../oflog/include/dcmtk/oflog/tchar.h \ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ ../../oflog/include/dcmtk/oflog/appender.h \ ../../ofstd/include/dcmtk/ofstd/ofmem.h \ ../../ofstd/include/dcmtk/ofstd/ofutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ ../../oflog/include/dcmtk/oflog/layout.h \ ../../oflog/include/dcmtk/oflog/streams.h \ @@ -481,44 +499,42 @@ segutils.o: segutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segutils.h \ + ../include/dcmtk/dcmseg/segtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -529,11 +545,9 @@ segutils.o: segutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -563,8 +577,4 @@ segutils.o: segutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h diff --git a/dcmseg/libsrc/segdoc.cc b/dcmseg/libsrc/segdoc.cc index 482c9319..1489d677 100644 --- a/dcmseg/libsrc/segdoc.cc +++ b/dcmseg/libsrc/segdoc.cc @@ -18,101 +18,151 @@ * Purpose: Class representing a Segmentation object * */ + #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/fgderimg.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgseg.h" +#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmseg/segdoc.h" #include "dcmtk/dcmseg/segment.h" #include "dcmtk/dcmseg/segutils.h" -#include "dcmtk/dcmiod/iodutil.h" -#include "dcmtk/dcmfg/fgseg.h" -#include "dcmtk/dcmfg/fgplanpo.h" -#include "dcmtk/dcmfg/fgplanor.h" -#include "dcmtk/dcmfg/fgfracon.h" -#include "dcmtk/dcmfg/fgfact.h" -#include "dcmtk/dcmfg/fgderimg.h" // default constructor (protected, instance creation via create() function) DcmSegmentation::DcmSegmentation() -: DcmSegmentation::IODImage(OFin_place >), - m_SegmentationSeries(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()), - m_EnhancedGeneralEquipmentModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()), - m_FG(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()), - m_DimensionModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()), - m_Frames(), - m_ImageType("DERIVED\\PRIMARY"), - m_ContentIdentificationMacro(), - m_SegmentationType(DcmSegTypes::ST_BINARY), - m_SegmentationFractionalType(DcmSegTypes::SFT_OCCUPANCY), - m_MaximumFractionalValue(DCM_MaximumFractionalValue), - m_Segments(), - m_FGInterface() + : DcmSegmentation::IODImage(OFin_place >) + , m_SegmentationSeries(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()) + , m_EnhancedGeneralEquipmentModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()) + , m_FG(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()) + , m_DimensionModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules()) + , m_Frames() + , m_ImageType("DERIVED\\PRIMARY") + , m_ContentIdentificationMacro() + , m_SegmentationType(DcmSegTypes::ST_BINARY) + , m_SegmentationFractionalType(DcmSegTypes::SFT_OCCUPANCY) + , m_MaximumFractionalValue(DCM_MaximumFractionalValue) + , m_Segments() + , m_FGInterface() { - DcmSegmentation::initIODRules(); + DcmSegmentation::initIODRules(); } - void DcmSegmentation::initIODRules() { - // ------------ Segmentation Image Module ------------- - - // Partly overrides rules from General Image Module - getRules()->addRule(new IODRule(DCM_ImageType, "2","1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - getRules()->addRule(new IODRule(DCM_SegmentationType, "1","1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - getRules()->addRule(new IODRule(DCM_SegmentationFractionalType, "1","1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - getRules()->addRule(new IODRule(DCM_MaximumFractionalValue, "1","1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - - // Re-use General Image Module instead of Segmentation Image Module - getRules()->addRule(new IODRule(DCM_LossyImageCompression, "1","1", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - getRules()->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n", "1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - getRules()->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1-n","1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - - // Override rule from General Series Module - getRules()->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1","1C", "SegmentationSeriesModule", DcmIODTypes::IE_SERIES), OFTrue); - getRules()->addRule(new IODRule(DCM_SeriesNumber, "1","1", "SegmentationSeriesModule", DcmIODTypes::IE_SERIES), OFTrue); - - // Instance Number is also used within Content Identification Macro, disable it there - m_ContentIdentificationMacro.getIODRules().deleteRule(DCM_InstanceNumber); + // ------------ Segmentation Image Module ------------- + + // Partly overrides rules from General Image Module + getRules()->addRule(new IODRule(DCM_ImageType, "2", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + getRules()->addRule(new IODRule(DCM_SegmentationType, "1", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + getRules()->addRule( + new IODRule(DCM_SegmentationFractionalType, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + getRules()->addRule( + new IODRule(DCM_MaximumFractionalValue, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + + // Re-use General Image Module instead of Segmentation Image Module + getRules()->addRule(new IODRule(DCM_LossyImageCompression, "1", "1", "GeneralImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + getRules()->addRule( + new IODRule(DCM_LossyImageCompressionMethod, "1-n", "1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + getRules()->addRule( + new IODRule(DCM_LossyImageCompressionRatio, "1-n", "1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + + // Override rule from General Series Module + getRules()->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence, + "1", + "1C", + "SegmentationSeriesModule", + DcmIODTypes::IE_SERIES), + OFTrue); + getRules()->addRule(new IODRule(DCM_SeriesNumber, "1", "1", "SegmentationSeriesModule", DcmIODTypes::IE_SERIES), + OFTrue); + + // Instance Number is also used within Content Identification Macro, disable it there + m_ContentIdentificationMacro.getIODRules().deleteRule(DCM_InstanceNumber); } - DcmSegmentation::~DcmSegmentation() { - clearData(); + clearData(); } - // static method for loading segmentation objects -OFCondition DcmSegmentation::loadFile(const OFString& filename, - DcmSegmentation*& segmentation) +OFCondition DcmSegmentation::loadFile(const OFString& filename, DcmSegmentation*& segmentation) { - DcmFileFormat dcmff; - DcmDataset *dataset = NULL; - OFCondition result = loadFile(dcmff, filename, dataset); - if (result.bad()) - return result; + DcmFileFormat dcmff; + DcmDataset* dataset = NULL; + OFCondition result = loadFile(dcmff, filename, dataset); + if (result.bad()) + return result; - return loadDataset(*dataset, segmentation); + return loadDataset(*dataset, segmentation); } - // static method for loading segmentation objects -OFCondition DcmSegmentation::loadDataset(DcmDataset& dataset, - DcmSegmentation*& segmentation) +OFCondition DcmSegmentation::loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation) { - OFCondition result = DcmSegmentation::decompress(dataset); - if (result.bad()) - return result; - - segmentation = new DcmSegmentation(); - if (segmentation == NULL) - { - return EC_MemoryExhausted; - } + segmentation = NULL; + OFCondition result = DcmSegmentation::decompress(dataset); + if (result.bad()) + return result; - return segmentation->read(dataset); + DcmSegmentation* temp = new DcmSegmentation(); + if (temp == NULL) + { + return EC_MemoryExhausted; + } + result = temp->read(dataset); + if (result.good()) + { + segmentation = temp; + } + else + { + delete segmentation; + } + return result; } +OFCondition DcmSegmentation::loadConcatenation(ConcatenationLoader& cl, + const OFString& concatenationUID, + DcmSegmentation*& segmentation) +{ + DcmDataset dset; + segmentation = NULL; + OFVector frames; + OFCondition result = cl.load(concatenationUID, &dset, frames); + if (result.good()) + { + segmentation = new DcmSegmentation(); + if (segmentation) + { + result = segmentation->readWithoutPixelData(dset); + if (result.good()) + { + segmentation->m_Frames = frames; + } + } + else + { + result = EC_MemoryExhausted; + } + } + if (result.bad()) + { + DcmIODUtil::freeContainer(frames); + delete segmentation; + } + return result; +} OFCondition DcmSegmentation::createBinarySegmentation(DcmSegmentation*& segmentation, const Uint16 rows, @@ -121,16 +171,15 @@ OFCondition DcmSegmentation::createBinarySegmentation(DcmSegmentation*& segmenta const ContentIdentificationMacro& contentIdentification) { - OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification); - if (result.bad()) - return result; + OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification); + if (result.bad()) + return result; - segmentation->m_SegmentationType = DcmSegTypes::ST_BINARY; + segmentation->m_SegmentationType = DcmSegTypes::ST_BINARY; - return result; + return result; } - OFCondition DcmSegmentation::createFractionalSegmentation(DcmSegmentation*& segmentation, const Uint16 rows, const Uint16 columns, @@ -139,475 +188,498 @@ OFCondition DcmSegmentation::createFractionalSegmentation(DcmSegmentation*& segm const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, const ContentIdentificationMacro& contentIdentification) { - OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification); - if (result.bad()) - return result; + OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification); + if (result.bad()) + return result; - segmentation->m_SegmentationType = DcmSegTypes::ST_FRACTIONAL; - segmentation->m_SegmentationFractionalType = fractType; - segmentation->m_MaximumFractionalValue.putUint16(maxFractionalValue); + segmentation->m_SegmentationType = DcmSegTypes::ST_FRACTIONAL; + segmentation->m_SegmentationFractionalType = fractType; + segmentation->m_MaximumFractionalValue.putUint16(maxFractionalValue); - return result; + return result; } - OFCondition DcmSegmentation::createCommon(DcmSegmentation*& segmentation, const Uint16 rows, const Uint16 columns, const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo, const ContentIdentificationMacro& contentIdentification) { - if ( (rows == 0) || (columns == 0) ) - { - DCMSEG_ERROR("Segmentation must have at least 1 row and 1 column"); - return EC_IllegalParameter; - } - - segmentation = new DcmSegmentation(); - if (segmentation == NULL) - return EC_MemoryExhausted; - - segmentation->getImagePixel().setRows(rows); - segmentation->getImagePixel().setColumns(columns); - - OFCondition result = segmentation->setContentIdentification(contentIdentification); - if (result.good()) - { - OFString tempstr; - contentIdentification.getInstanceNumber(tempstr); - result = segmentation->getGeneralImage().setInstanceNumber(tempstr); - if (result.bad()) + if ((rows == 0) || (columns == 0)) { - delete segmentation; - segmentation = NULL; - return EC_InvalidValue; + DCMSEG_ERROR("Segmentation must have at least 1 row and 1 column"); + return EC_IllegalParameter; } - DcmIODUtil::setContentDateAndTimeNow(segmentation->getGeneralImage()); - result = segmentation->setEquipmentInfo(equipmentInfo, OFTrue /* check */); - } + segmentation = new DcmSegmentation(); + if (segmentation == NULL) + return EC_MemoryExhausted; - if (result.bad()) - { - delete segmentation; - segmentation = NULL; - } + segmentation->getImagePixel().setRows(rows); + segmentation->getImagePixel().setColumns(columns); - return result; -} + OFCondition result = segmentation->setContentIdentification(contentIdentification); + if (result.good()) + { + OFString tempstr; + contentIdentification.getInstanceNumber(tempstr); + result = segmentation->getGeneralImage().setInstanceNumber(tempstr); + if (result.bad()) + { + delete segmentation; + segmentation = NULL; + return EC_InvalidValue; + } + DcmIODUtil::setContentDateAndTimeNow(segmentation->getGeneralImage()); + result = segmentation->setEquipmentInfo(equipmentInfo, OFTrue /* check */); + } -FGDerivationImage* DcmSegmentation::createDerivationImageFG(const OFVector< ImageSOPInstanceReferenceMacro >& derivationImages, - const OFString& derivationDescription) -{ - CodeSequenceMacro derivationCode("113076", "DCM", "Segmentation"); - CodeSequenceMacro purpose("121322", "DCM", "Source Image for Image Processing Operation"); - return FGDerivationImage::createMinimal(derivationImages, - derivationDescription, - derivationCode, - purpose); + if (result.bad()) + { + delete segmentation; + segmentation = NULL; + } + + return result; } +FGDerivationImage* +DcmSegmentation::createDerivationImageFG(const OFVector& derivationImages, + const OFString& derivationDescription) +{ + CodeSequenceMacro derivationCode("113076", "DCM", "Segmentation"); + CodeSequenceMacro purpose("121322", "DCM", "Source Image for Image Processing Operation"); + return FGDerivationImage::createMinimal(derivationImages, derivationDescription, derivationCode, purpose); +} -OFCondition DcmSegmentation::read(DcmItem &dataset) +OFCondition DcmSegmentation::read(DcmItem& dataset) { - OFString sopClass; - if (DcmIODUtil::checkSOPClass(&dataset, UID_SegmentationStorage, sopClass).bad()) - { - DCMSEG_ERROR("Given file does not seem to be a segmentation storage object since SOP class is: " << sopClass); - return IOD_EC_WrongSOPClass; - } + OFCondition result = readWithoutPixelData(dataset); + if (result.good()) + result = readFrames(dataset); + return result; +} - // Read attributes in base classes - DcmSegmentation::IODImage::read(dataset); +OFCondition DcmSegmentation::readWithoutPixelData(DcmItem& dataset) +{ + OFString sopClass; + if (DcmIODUtil::checkSOPClass(&dataset, UID_SegmentationStorage, sopClass).bad()) + { + DCMSEG_ERROR("Given file does not seem to be a segmentation storage object since SOP class is: " << sopClass); + return IOD_EC_WrongSOPClass; + } - // Read Segmentation Series Module - m_SegmentationSeries.read(dataset); + // Read attributes in base classes + DcmSegmentation::IODImage::read(dataset); - // Read Enhanced General Equipment (i.e. make sure all type 1 elements are - // there, which is not checked in General Equipment Module being part of - // DcmIODImage. - m_EnhancedGeneralEquipmentModule.read(dataset); + // Read Segmentation Series Module + m_SegmentationSeries.read(dataset); - // Read functional groups module - m_FG.read(dataset); + // Read Enhanced General Equipment (i.e. make sure all type 1 elements are + // there, which is not checked in General Equipment Module being part of + // DcmIODImage. + m_EnhancedGeneralEquipmentModule.read(dataset); - // Read functional groups itself - m_FGInterface.read(dataset); + // Read functional groups module + m_FG.read(dataset); - // Read dimension information - m_DimensionModule.read(dataset); + // Read functional groups itself + m_FGInterface.read(dataset); - readSegmentationType(dataset); + // Read dimension information + m_DimensionModule.read(dataset); - readSegments(dataset); + readSegmentationType(dataset); - readFrames(dataset); + readSegments(dataset); - readSegmentationFractionalType(dataset); + readSegmentationFractionalType(dataset); - m_ContentIdentificationMacro.read(dataset); + m_ContentIdentificationMacro.read(dataset); - // Read specific segmentation elements - DcmIODUtil::getAndCheckElementFromDataset(dataset, m_MaximumFractionalValue, getRules()->getByTag(DCM_MaximumFractionalValue)); + // Read specific segmentation elements + DcmIODUtil::getAndCheckElementFromDataset( + dataset, m_MaximumFractionalValue, getRules()->getByTag(DCM_MaximumFractionalValue)); - return EC_Normal; + return EC_Normal; } - void DcmSegmentation::setCheckFGOnWrite(const OFBool doCheck) { - m_FGInterface.setCheckOnWrite(doCheck); + m_FGInterface.setCheckOnWrite(doCheck); } - OFBool DcmSegmentation::getCheckFGOnWrite() { - return m_FGInterface.getCheckOnWrite(); + return m_FGInterface.getCheckOnWrite(); } - -OFCondition DcmSegmentation::write(DcmItem &dataset) +OFCondition DcmSegmentation::writeWithSeparatePixelData(DcmItem& dataset, Uint8*& pixData, size_t& pixDataLength) { - // FGInterface::write() will know whether it has to check FG structure - // so we do not need to check FG structure here (OFFalse). - if (!check(OFFalse)) - { - return IOD_EC_InvalidObject; - } - - OFCondition result; + // FGInterface::write() will know whether it has to check FG structure + // so we do not need to check FG structure here (OFFalse). + if (!check(OFFalse)) + { + return IOD_EC_InvalidObject; + } - // -- Set constant default values written by external modules -- - getGeneralImage().setLossyImageCompression("00"); - getGeneralImage().setImageType(m_ImageType); - getSOPCommon().setSOPClassUID(UID_SegmentationStorage); + OFCondition result; - // -- Extra Study level data -- + // -- Set constant default values written by external modules -- + getGeneralImage().setLossyImageCompression("00"); + getGeneralImage().setImageType(m_ImageType); + getSOPCommon().setSOPClassUID(UID_SegmentationStorage); - // Enhanced Equipment Module - if (result.good()) result = m_EnhancedGeneralEquipmentModule.write(dataset); + // -- Extra Study level data -- - // -- Extra Series level data -- + // Enhanced Equipment Module + if (result.good()) + result = m_EnhancedGeneralEquipmentModule.write(dataset); - // Write segmentation-specific series level attribute (Segmentation Series Module) - if (result.good()) result = m_SegmentationSeries.write(dataset); + // -- Extra Series level data -- - // -- Extra Image level data -- + // Write segmentation-specific series level attribute (Segmentation Series Module) + if (result.good()) + result = m_SegmentationSeries.write(dataset); - // Write Multi-Frame Functional Groups Module - if (result.good()) result = writeMultiFrameFunctionalGroupsModule(dataset); + // -- Extra Image level data -- - // Write Multi-Frame Dimension Module - if (result.good()) result = writeMultiFrameDimensionModule(dataset); + // Write Multi-Frame Functional Groups Module + if (result.good()) + result = writeMultiFrameFunctionalGroupsModule(dataset); - // Write segmentation image module and image pixel module - if (result.good()) result = writeSegmentationImageModule(dataset); + // Write Multi-Frame Dimension Module + if (result.good()) + result = writeMultiFrameDimensionModule(dataset); - // -- Write common multi frame image IOD attributes -- + // Write segmentation image module and image pixel module + if (result.good()) + result = writeSegmentationImageModule(dataset); + + // -- Write common multi frame image IOD attributes -- + + // Patient Module + // General Study Module + // General Series Module + // Frame of Reference Module + // General Equipment Module + // General Image Module + // Multi-frame Functional Groups Module (except functional groups itself) + // SOP Common Module + // Common Instance Reference Module + if (result.good()) + result = DcmSegmentation::IODImage::write(dataset); - // Patient Module - // General Study Module - // General Series Module - // Frame of Reference Module - // General Equipment Module - // General Image Module - // Multi-frame Functional Groups Module (except functional groups itself) - // SOP Common Module - // Common Instance Reference Module - if (result.good()) result = DcmSegmentation::IODImage::write(dataset); + // Write frame pixel data + if (result.good()) + { + Uint32 numFrames = DcmIODUtil::limitMaxFrames( + m_Frames.size(), "More than 2147483647 frames provided, will only write 2147483647"); + Uint16 rows, cols; + rows = cols = 0; + getImagePixel().getRows(rows); + getImagePixel().getColumns(cols); + result = getTotalBytesRequired(rows, cols, numFrames, pixDataLength); + if (result.bad()) + return result; + + pixData = new Uint8[pixDataLength]; + if (!pixData) + return EC_MemoryExhausted; + + if (m_SegmentationType == DcmSegTypes::ST_BINARY) + result = writeBinaryFrames(pixData, rows, cols, pixDataLength); + else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL) + result = writeFractionalFrames(pixData, numFrames, pixDataLength); + else + result = SG_EC_UnknownSegmentationType; + if (result.bad()) + { + delete[] pixData; + pixData = NULL; + pixDataLength = 0; + } + } - return result; + return result; } - FGInterface& DcmSegmentation::getFunctionalGroups() { - return m_FGInterface; + return m_FGInterface; } +IODMultiFrameFGModule::ConcatenationInfo& DcmSegmentation::getConcatenationInfo() +{ + return m_FG.getConcatenationInfo(); +} size_t DcmSegmentation::getNumberOfFrames() { - return m_FGInterface.getNumberOfFrames(); + return m_FGInterface.getNumberOfFrames(); } - - size_t DcmSegmentation::getNumberOfSegments() { - return m_Segments.size(); + return m_Segments.size(); } - IODGeneralEquipmentModule& DcmSegmentation::getEquipment() { - return DcmSegmentation::IODImage::getEquipment(); + return DcmSegmentation::IODImage::getEquipment(); } - -IODSegmentationSeriesModule & DcmSegmentation::getSegmentationSeriesModule() +IODSegmentationSeriesModule& DcmSegmentation::getSegmentationSeriesModule() { - return m_SegmentationSeries; + return m_SegmentationSeries; } - -OFCondition DcmSegmentation::addSegment(DcmSegment* seg, - Uint16& segmentNumber) +OFCondition DcmSegmentation::addSegment(DcmSegment* seg, Uint16& segmentNumber) { - segmentNumber = 0; - if (seg == NULL) - return EC_IllegalParameter; - - if (m_Segments.size() >= DCM_SEG_MAX_SEGMENTS) - { - return SG_EC_MaxSegmentsReached; - } - - // Casting is safe since we made sure number of segments fits into 16 bit - segmentNumber = OFstatic_cast(Uint16, m_Segments.size() + 1); - m_Segments.push_back(seg); - return EC_Normal; -} + segmentNumber = 0; + if (seg == NULL) + return EC_IllegalParameter; + if (m_Segments.size() >= DCM_SEG_MAX_SEGMENTS) + { + return SG_EC_MaxSegmentsReached; + } + + // Casting is safe since we made sure number of segments fits into 16 bit + segmentNumber = OFstatic_cast(Uint16, m_Segments.size() + 1); + m_Segments.push_back(seg); + return EC_Normal; +} OFCondition DcmSegmentation::addFrame(Uint8* pixData) { - OFCondition result; + OFCondition result; - Uint16 rows, cols; - if (getImagePixel().getRows(rows).good() && getImagePixel().getColumns(cols).good()) - { - DcmIODTypes::Frame* frame = NULL; - if (m_SegmentationType == DcmSegTypes::ST_BINARY) - { - frame = DcmSegUtils::packBinaryFrame(pixData, rows, cols); - if (!frame) - { - result = IOD_EC_CannotInsertFrame; - } - } - else // fractional + Uint16 rows, cols; + if (getImagePixel().getRows(rows).good() && getImagePixel().getColumns(cols).good()) { - frame = new DcmIODTypes::Frame(); - if (frame) - { - frame->length = rows*cols; - frame->pixData = new Uint8[frame->length]; - if (frame->pixData) + DcmIODTypes::Frame* frame = NULL; + if (m_SegmentationType == DcmSegTypes::ST_BINARY) { - memcpy(frame->pixData, pixData, frame->length); + frame = DcmSegUtils::packBinaryFrame(pixData, rows, cols); + if (!frame) + { + result = IOD_EC_CannotInsertFrame; + } } - else + else // fractional + { + frame = new DcmIODTypes::Frame(); + if (frame) + { + frame->length = rows * cols; + frame->pixData = new Uint8[frame->length]; + if (frame->pixData) + { + memcpy(frame->pixData, pixData, frame->length); + } + else + { + delete frame; + result = EC_MemoryExhausted; + } + } + else + result = EC_MemoryExhausted; + } + if (result.good()) { - delete frame; - result = EC_MemoryExhausted; + m_Frames.push_back(frame); } - } - else - result = EC_MemoryExhausted; } - if (result.good()) + else { - m_Frames.push_back(frame); + DCMSEG_ERROR("Cannot add frame since rows and/or columns are unknown"); + result = IOD_EC_CannotInsertFrame; } - } - else - { - DCMSEG_ERROR("Cannot add frame since rows and/or columns are unknown"); - result = IOD_EC_CannotInsertFrame; - } - return result; + return result; } - SOPInstanceReferenceMacro& DcmSegmentation::getReferencedPPS() { - return getSeries().getReferencedPPS(); + return getSeries().getReferencedPPS(); } - const DcmIODTypes::Frame* DcmSegmentation::getFrame(const size_t& frameNo) { - if (frameNo > m_Frames.size() - 1) - { - return NULL; - } + if (frameNo > m_Frames.size() - 1) + { + return NULL; + } - return m_Frames[frameNo]; + return m_Frames[frameNo]; } - -void DcmSegmentation::getFramesForSegment(const size_t& segmentNumber, - OFVector& frameNumbers) +void DcmSegmentation::getFramesForSegment(const size_t& segmentNumber, OFVector& frameNumbers) { - size_t numFrames = getNumberOfFrames(); - for (size_t count = 0; count < numFrames; count++) - { - FGSegmentation* fg = OFstatic_cast(FGSegmentation*, m_FGInterface.get(OFstatic_cast(Uint32, count), DcmFGTypes::EFG_SEGMENTATION)); - if (fg == NULL) + size_t numFrames = getNumberOfFrames(); + for (size_t count = 0; count < numFrames; count++) { - DCMSEG_ERROR("Cannot get segmentation functional group for frame " << count); - return; - } - Uint16 refSeg; - if (fg->getReferencedSegmentNumber(refSeg).good()) - { - if (refSeg == segmentNumber) - { - frameNumbers.push_back(count); - } + FGSegmentation* fg = OFstatic_cast( + FGSegmentation*, m_FGInterface.get(OFstatic_cast(Uint32, count), DcmFGTypes::EFG_SEGMENTATION)); + if (fg == NULL) + { + DCMSEG_ERROR("Cannot get segmentation functional group for frame " << count); + return; + } + Uint16 refSeg; + if (fg->getReferencedSegmentNumber(refSeg).good()) + { + if (refSeg == segmentNumber) + { + frameNumbers.push_back(count); + } + } } - } } - OFCondition DcmSegmentation::addForAllFrames(const FGBase& group) { - return m_FGInterface.addShared(group); + return m_FGInterface.addShared(group); } - -OFCondition DcmSegmentation::addFrame(Uint8* pixData, - const Uint16 segmentNumber, - const OFVector& perFrameInformation) +OFCondition +DcmSegmentation::addFrame(Uint8* pixData, const Uint16 segmentNumber, const OFVector& perFrameInformation) { - Uint32 frameNo = OFstatic_cast(Uint32, m_Frames.size()); // will be the index of the frame (counted from 0) - OFCondition result; - - // Check input parameters - if ( pixData == NULL ) - { - DCMSEG_ERROR("No pixel data provided or zero length"); - result = EC_IllegalParameter; - } - if (segmentNumber > m_Segments.size() ) - { - DCMSEG_ERROR("Cannot add frame: Segment with given number " << segmentNumber << " does not exist"); - result = SG_EC_NoSuchSegment; - } - if (result.bad()) - return result; + Uint32 frameNo = OFstatic_cast(Uint32, m_Frames.size()); // will be the index of the frame (counted from 0) + OFCondition result; - OFVector::const_iterator it = perFrameInformation.begin(); - while (it != perFrameInformation.end()) - { - result = (*it)->check(); - if (result.bad()) + // Check input parameters + if (pixData == NULL) { - DCMSEG_ERROR("Could not add new frame since functional group of type: " << (*it)->getType() << " is invalid: " << result.text()); - break; + DCMSEG_ERROR("No pixel data provided or zero length"); + result = EC_IllegalParameter; + } + if (segmentNumber > m_Segments.size()) + { + DCMSEG_ERROR("Cannot add frame: Segment with given number " << segmentNumber << " does not exist"); + result = SG_EC_NoSuchSegment; } - result = m_FGInterface.addPerFrame(frameNo, *(*it)); if (result.bad()) + return result; + + OFVector::const_iterator it = perFrameInformation.begin(); + while (it != perFrameInformation.end()) { - DCMSEG_ERROR("Could not add new frame since functional group of type " << (*it)->getType() << ": " << result.text()); - break; + result = (*it)->check(); + if (result.bad()) + { + DCMSEG_ERROR("Could not add new frame since functional group of type: " + << (*it)->getType() << " is invalid: " << result.text()); + break; + } + result = m_FGInterface.addPerFrame(frameNo, *(*it)); + if (result.bad()) + { + DCMSEG_ERROR("Could not add new frame since functional group of type " << (*it)->getType() << ": " + << result.text()); + break; + } + it++; } - it++; - } - // Now also add Segmentation Functional Group - if (result.good()) - { - FGSegmentation seg; - result = seg.setReferencedSegmentNumber(segmentNumber); + // Now also add Segmentation Functional Group if (result.good()) { - result = m_FGInterface.addPerFrame(frameNo, seg); + FGSegmentation seg; + result = seg.setReferencedSegmentNumber(segmentNumber); + if (result.good()) + { + result = m_FGInterface.addPerFrame(frameNo, seg); + } + else + { + DCMSEG_ERROR("Could not add new frame, invalid segment number " << segmentNumber << ": " << result.text()); + } } - else + + // Insert pixel data + if (result.good()) { - DCMSEG_ERROR("Could not add new frame, invalid segment number " << segmentNumber << ": " << result.text()); + result = addFrame(pixData); } - } - - // Insert pixel data - if (result.good()) - { - result = addFrame(pixData); - } - // Cleanup any per-frame groups that might have been inserted and return - if (result.bad()) - { - for (OFVector::const_iterator it2 = perFrameInformation.begin(); it2 != perFrameInformation.end(); it2++ ) + // Cleanup any per-frame groups that might have been inserted and return + if (result.bad()) { - m_FGInterface.deletePerFrame(frameNo, (*it2)->getType()); + for (OFVector::const_iterator it2 = perFrameInformation.begin(); it2 != perFrameInformation.end(); + it2++) + { + m_FGInterface.deletePerFrame(frameNo, (*it2)->getType()); + } } - } - return result; + return result; } - ContentIdentificationMacro& DcmSegmentation::getContentIdentification() { - return m_ContentIdentificationMacro; + return m_ContentIdentificationMacro; } - IODMultiframeDimensionModule& DcmSegmentation::getDimensions() { - return m_DimensionModule; + return m_DimensionModule; } - -OFCondition DcmSegmentation::setLossyImageCompressionFlag(const OFString& ratios, - const OFString& methods, - const OFBool checkValues) +OFCondition +DcmSegmentation::setLossyImageCompressionFlag(const OFString& ratios, const OFString& methods, const OFBool checkValues) { - OFCondition result = getGeneralImage().setLossyImageCompression("01"); - if (result.good() || !checkValues) - result = getGeneralImage().setLossyImageCompressionMethod(methods); - if (result.good() || !checkValues) - result = getGeneralImage().setLossyImageCompressionRatio(ratios); + OFCondition result = getGeneralImage().setLossyImageCompression("01"); + if (result.good() || !checkValues) + result = getGeneralImage().setLossyImageCompressionMethod(methods); + if (result.good() || !checkValues) + result = getGeneralImage().setLossyImageCompressionRatio(ratios); - if (checkValues) - return result; - else - return EC_Normal; + if (checkValues) + return result; + else + return EC_Normal; } - -OFCondition DcmSegmentation::saveFile(const OFString& filename, - const E_TransferSyntax writeXfer) +OFCondition DcmSegmentation::saveFile(const OFString& filename, const E_TransferSyntax writeXfer) { - if ( (writeXfer != EXS_LittleEndianExplicit) - && (writeXfer != EXS_BigEndianExplicit) - && (writeXfer != EXS_LittleEndianImplicit) + if ((writeXfer != EXS_LittleEndianExplicit) && (writeXfer != EXS_BigEndianExplicit) + && (writeXfer != EXS_LittleEndianImplicit) #ifdef WITH_ZLIB - && (writeXfer != EXS_DeflatedLittleEndianExplicit) + && (writeXfer != EXS_DeflatedLittleEndianExplicit) #endif - ) - { - DcmXfer ts(writeXfer); + ) + { + DcmXfer ts(writeXfer); #ifdef WITH_ZLIB - DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName() << ": Can only write uncompressed or Deflated)"); + DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName() + << ": Can only write uncompressed or Deflated)"); #else - if (writeXfer == EXS_DeflatedLittleEndianExplicit) + if (writeXfer == EXS_DeflatedLittleEndianExplicit) + { + DCMSEG_ERROR("Cannot write transfer syntax: " + << ts.getXferName() << ": Deflate (ZLIB) support disabled, can only write uncompressed"); + } +#endif + return EC_CannotChangeRepresentation; + } + + DcmFileFormat dcmff; + OFCondition result = writeDataset(*(dcmff.getDataset())); + if (result.good()) { - DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName() << ": Deflate (ZLIB) support disabled, can only write uncompressed"); + result = dcmff.saveFile(filename.c_str(), writeXfer); + } + if (result.bad()) + { + DCMSEG_ERROR("Cannot save segmentation document to file " << filename << ": " << result.text()); } -#endif - return EC_CannotChangeRepresentation; - } - - DcmFileFormat dcmff; - OFCondition result = write( *(dcmff.getDataset()) ); - if (result.good()) - { - result = dcmff.saveFile(filename.c_str(), writeXfer); - } - if (result.bad()) - { - DCMSEG_ERROR("Cannot save segmentation document to file " << filename << ": " << result.text()); - } - - return result; -} + return result; +} /* -- Setter for DICOM attributes -- */ @@ -615,197 +687,182 @@ OFCondition DcmSegmentation::setEquipmentInfo(const IODGeneralEquipmentModule::E const OFBool checkValue) { - if (checkValue) - { - if ( equipmentInfo.m_Manufacturer.empty() - || equipmentInfo.m_ManufacturerModelName.empty() - || equipmentInfo.m_DeviceSerialNumber.empty() - || equipmentInfo.m_SoftwareVersions.empty() ) + if (checkValue) { - return EC_InvalidValue; + if (equipmentInfo.m_Manufacturer.empty() || equipmentInfo.m_ManufacturerModelName.empty() + || equipmentInfo.m_DeviceSerialNumber.empty() || equipmentInfo.m_SoftwareVersions.empty()) + { + return EC_InvalidValue; + } } - } - OFCondition result = getEquipment().setManufacturer(equipmentInfo.m_Manufacturer, checkValue); - if ( result.good() ) - result = getEquipment().setManufacturerModelName(equipmentInfo.m_ManufacturerModelName, checkValue); - if (result.good()) - result = getEquipment().setDeviceSerialNumber(equipmentInfo.m_DeviceSerialNumber, checkValue); - if (result.good()) - result = getEquipment().setSoftwareVersions(equipmentInfo.m_SoftwareVersions, checkValue); + OFCondition result = getEquipment().setManufacturer(equipmentInfo.m_Manufacturer, checkValue); + if (result.good()) + result = getEquipment().setManufacturerModelName(equipmentInfo.m_ManufacturerModelName, checkValue); + if (result.good()) + result = getEquipment().setDeviceSerialNumber(equipmentInfo.m_DeviceSerialNumber, checkValue); + if (result.good()) + result = getEquipment().setSoftwareVersions(equipmentInfo.m_SoftwareVersions, checkValue); - return result; + return result; } - OFCondition DcmSegmentation::setContentIdentification(const ContentIdentificationMacro& contentIdentification, const OFBool checkValue) { - // Instance Number and Content Label must be filled out, rest can be empty - OFCondition result; - if (checkValue) - { - result = OFconst_cast(ContentIdentificationMacro*,&contentIdentification)->check(); - } - if (result.bad()) - return result; + // Instance Number and Content Label must be filled out, rest can be empty + OFCondition result; + if (checkValue) + { + result = OFconst_cast(ContentIdentificationMacro*, &contentIdentification)->check(); + } + if (result.bad()) + return result; - m_ContentIdentificationMacro = contentIdentification; + m_ContentIdentificationMacro = contentIdentification; - return result; + return result; } - - /* -- Getter for DICOM attributes -- */ DcmSegment* DcmSegmentation::getSegment(const unsigned int segmentNumber) { - // check for invalid index - if ( (segmentNumber == 0) || (segmentNumber > m_Segments.size()) ) - { - return NULL; - } - - // logical segment numbering starts with 1, so subtract 1 for vector index - return m_Segments[segmentNumber-1]; -} + // check for invalid index + if ((segmentNumber == 0) || (segmentNumber > m_Segments.size())) + { + return NULL; + } + // logical segment numbering starts with 1, so subtract 1 for vector index + return m_Segments[segmentNumber - 1]; +} -OFBool DcmSegmentation::getSegmentNumber(const DcmSegment* segment, - unsigned int& segmentNumber) +OFBool DcmSegmentation::getSegmentNumber(const DcmSegment* segment, unsigned int& segmentNumber) { - segmentNumber = 0; - size_t max = m_Segments.size(); - for (size_t count = 0; count < max; count++) - { - if (m_Segments.at(count) == segment) - { - // logical segment numbering starts with 1 but vector index with 0 - segmentNumber = OFstatic_cast(unsigned int, count + 1); - return OFTrue; - } - } - // not found - return OFFalse; + segmentNumber = 0; + size_t max = m_Segments.size(); + for (size_t count = 0; count < max; count++) + { + if (m_Segments.at(count) == segment) + { + // logical segment numbering starts with 1 but vector index with 0 + segmentNumber = OFstatic_cast(unsigned int, count + 1); + return OFTrue; + } + } + // not found + return OFFalse; } - -OFCondition DcmSegmentation::getModality(OFString& value, - const long signed int pos) const +OFCondition DcmSegmentation::getModality(OFString& value, const long signed int pos) const { - (void)pos; - // Fixed for Segmentations to value "SEG" - value = "SEG"; - return EC_Normal; + (void)pos; + // Fixed for Segmentations to value "SEG" + value = "SEG"; + return EC_Normal; } - -OFCondition DcmSegmentation::importFromSourceImage(const OFString& filename, - const bool takeOverCharset) +OFCondition DcmSegmentation::importFromSourceImage(const OFString& filename, const bool takeOverCharset) { - DcmFileFormat dcmff; - OFCondition result = dcmff.loadFile(filename); - if (result.good()) - { - return importFromSourceImage(*(dcmff.getDataset()), takeOverCharset); - } - return result; + DcmFileFormat dcmff; + OFCondition result = dcmff.loadFile(filename); + if (result.good()) + { + return importFromSourceImage(*(dcmff.getDataset()), takeOverCharset); + } + return result; } - -OFCondition DcmSegmentation::importFromSourceImage(DcmItem& dataset, - const bool takeOverCharset) +OFCondition DcmSegmentation::importFromSourceImage(DcmItem& dataset, const bool takeOverCharset) { - OFString FoR; - dataset.findAndGetOFStringArray(DCM_FrameOfReferenceUID, FoR); - return DcmIODCommon::importHierarchy( - dataset, - OFTrue, // Patient - OFTrue, // Study - !FoR.empty(), // Frame of Reference - OFFalse, // Series - takeOverCharset); + OFString FoR; + dataset.findAndGetOFStringArray(DCM_FrameOfReferenceUID, FoR); + return DcmIODCommon::importHierarchy(dataset, + OFTrue, // Patient + OFTrue, // Study + !FoR.empty(), // Frame of Reference + OFFalse, // Series + takeOverCharset); } - /* protected functions */ OFCondition DcmSegmentation::writeSegments(DcmItem& item) { - OFCondition result; - DcmIODUtil::writeSubSequence >(result, DCM_SegmentSequence, m_Segments, item, "1-n", "1", "SegmentationImageModule"); - return result; + OFCondition result; + DcmIODUtil::writeSubSequence >( + result, DCM_SegmentSequence, m_Segments, item, "1-n", "1", "SegmentationImageModule"); + return result; } - OFCondition DcmSegmentation::readSegments(DcmItem& item) { - return DcmIODUtil::readSubSequence >(item, DCM_SegmentSequence, m_Segments, "1-n", "1", "SegmentationImageModule"); + return DcmIODUtil::readSubSequence >( + item, DCM_SegmentSequence, m_Segments, "1-n", "1", "SegmentationImageModule"); } - OFCondition DcmSegmentation::readFrames(DcmItem& dataset) { - OFCondition result; - Uint16 allocated, stored, high, spp, pixelRep, rows, cols, numberOfFrames; - allocated = stored = high = spp = rows = cols = numberOfFrames = 0; - pixelRep = 2; // invalid value for this attribute - OFString colorModel; - - /* check the typical image pixel attributes and get correct(ed) values */ - result = getAndCheckImagePixelAttributes(dataset, allocated, stored, high, spp, pixelRep, rows, cols, numberOfFrames, colorModel); - if (result.bad()) - return result; + OFCondition result; + Uint16 allocated, stored, high, spp, pixelRep, rows, cols, numberOfFrames; + allocated = stored = high = spp = rows = cols = numberOfFrames = 0; + pixelRep = 2; // invalid value for this attribute + OFString colorModel; + + /* check the typical image pixel attributes and get correct(ed) values */ + result = getAndCheckImagePixelAttributes( + dataset, allocated, stored, high, spp, pixelRep, rows, cols, numberOfFrames, colorModel); + if (result.bad()) + return result; - /* Check length of pixel data element */ - DcmElement* pixelData = NULL; - if (dataset.findAndGetElement(DCM_PixelData, pixelData).bad()) - return IOD_EC_InvalidPixelData; - if (!checkPixDataLength(pixelData, rows, cols, numberOfFrames)) - return IOD_EC_InvalidPixelData; - - /* Get pixel data values */ - Uint8* pixels = NULL; - result = pixelData->getUint8Array(pixels); - if (result.bad()) - { - DCMSEG_ERROR("Cannot read pixel data"); - return result; - } - - /* Read all frames into dedicated data structure */ - size_t pixelsPerFrame = OFstatic_cast(size_t, rows) * cols; - if (m_SegmentationType == DcmSegTypes::ST_BINARY) - { - result = extractFrames(pixels, numberOfFrames, pixelsPerFrame, m_Frames); - if (result.bad()) - { + /* Check length of pixel data element */ + DcmElement* pixelData = NULL; + if (dataset.findAndGetElement(DCM_PixelData, pixelData).bad()) + return IOD_EC_InvalidPixelData; + if (!checkPixDataLength(pixelData, rows, cols, numberOfFrames)) + return IOD_EC_InvalidPixelData; + + /* Get pixel data values */ + Uint8* pixels = NULL; + result = pixelData->getUint8Array(pixels); + if (result.bad()) + { + DCMSEG_ERROR("Cannot read pixel data"); return result; } - } - else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL) - { - for (size_t count = 0; count < numberOfFrames; count++) - { - DcmIODTypes::Frame *frame = new DcmIODTypes::Frame(); - if (!frame) return EC_MemoryExhausted; - frame->length = pixelsPerFrame; - frame->pixData= new Uint8[pixelsPerFrame]; - if (!frame->pixData) - { - delete frame; - return EC_MemoryExhausted; - } - memcpy(frame->pixData, pixels + count* pixelsPerFrame, pixelsPerFrame); - m_Frames.push_back(frame); - } - } - - return result; -} + /* Read all frames into dedicated data structure */ + size_t pixelsPerFrame = OFstatic_cast(size_t, rows) * cols; + if (m_SegmentationType == DcmSegTypes::ST_BINARY) + { + result = DcmIODUtil::extractBinaryFrames(pixels, numberOfFrames, pixelsPerFrame, m_Frames); + if (result.bad()) + { + return result; + } + } + else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL) + { + for (size_t count = 0; count < numberOfFrames; count++) + { + DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); + if (!frame) + return EC_MemoryExhausted; + frame->length = pixelsPerFrame; + frame->pixData = new Uint8[pixelsPerFrame]; + if (!frame->pixData) + { + delete frame; + return EC_MemoryExhausted; + } + memcpy(frame->pixData, pixels + count * pixelsPerFrame, pixelsPerFrame); + m_Frames.push_back(frame); + } + } + return result; +} OFCondition DcmSegmentation::getAndCheckImagePixelAttributes(DcmItem& dataset, Uint16& allocated, @@ -818,663 +875,592 @@ OFCondition DcmSegmentation::getAndCheckImagePixelAttributes(DcmItem& dataset, Uint16& numberOfFrames, OFString& colorModel) { - OFBool fail = OFFalse; - dataset.findAndGetUint16(DCM_BitsAllocated, allocated); - dataset.findAndGetUint16(DCM_BitsStored, stored); - dataset.findAndGetUint16(DCM_HighBit, high); - dataset.findAndGetUint16(DCM_PixelRepresentation, pixelRep); - dataset.findAndGetUint16(DCM_SamplesPerPixel, spp); - dataset.findAndGetOFStringArray(DCM_PhotometricInterpretation, colorModel); - - /* Rows and Columns */ - OFCondition result = getImagePixel().getRows(rows); - if (result.good()) - result = getImagePixel().getColumns(cols); - if (result.bad()) - { - DCMSEG_ERROR("Cannot find Rows or Columns in dataset"); - fail = OFTrue; - } - - /* Number of Frames */ - Sint32 numFrames = 0; - result = m_FG.getNumberOfFrames(numFrames); - if (result.bad()) - { - DCMSEG_ERROR("Number of Frames not set"); - fail = OFTrue; - } - else - { - if ( numFrames < 0 ) - { - DCMSEG_ERROR("Number of Frames must be greater than 0"); - fail = OFTrue; + OFBool fail = OFFalse; + dataset.findAndGetUint16(DCM_BitsAllocated, allocated); + dataset.findAndGetUint16(DCM_BitsStored, stored); + dataset.findAndGetUint16(DCM_HighBit, high); + dataset.findAndGetUint16(DCM_PixelRepresentation, pixelRep); + dataset.findAndGetUint16(DCM_SamplesPerPixel, spp); + dataset.findAndGetOFStringArray(DCM_PhotometricInterpretation, colorModel); + + /* Rows and Columns */ + OFCondition result = getImagePixel().getRows(rows); + if (result.good()) + result = getImagePixel().getColumns(cols); + if (result.bad()) + { + DCMSEG_ERROR("Cannot find Rows or Columns in dataset"); + fail = OFTrue; + } + + /* Number of Frames */ + Sint32 numFrames = 0; + result = m_FG.getNumberOfFrames(numFrames); + if (result.bad()) + { + DCMSEG_ERROR("Number of Frames not set"); + fail = OFTrue; } else { - numberOfFrames = OFstatic_cast(Uint16, numFrames); - } - } - - Uint16 depth = 0; - if (m_SegmentationType == DcmSegTypes::ST_BINARY) - depth = 1; - else - depth = 8; - - if (allocated != depth) - { - DCMSEG_WARN("Bits Allocated is not set correctly (" << allocated << ", ignored), assuming value " << depth << " as required for " << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); - allocated = depth; - } - if (stored != depth) - { - DCMSEG_WARN("Bits Stored is not set correctly (" << stored << ", ignored), assuming value " << depth << " as required for " << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); - stored = depth; - } - if (high != depth-1) - { - DCMSEG_WARN("High Bit is not set correctly (" << high << ", ignored), assuming value " << depth-1 << " as required for " << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); - high = depth -1; - } - if (spp != 1) - { - DCMSEG_WARN("Samples per Pixel is not set correctly (" << spp << ", ignored), assuming value 1 as required for segmentation objects"); - spp = 1; - } - if (pixelRep != 0) - { - DCMSEG_WARN("Pixel Representation is not set correctly (" << pixelRep << ", ignored), assuming value 0 as required for segmentation objects"); - pixelRep = 0; - } - if (colorModel != "MONOCHROME2") - { - DCMSEG_WARN("Photometric Interpretation is not set correctly (ignored), assuming value MONOCHROME2 as required for segmentation objects"); - colorModel = "MONOCHROME2"; - } - if (rows == 0) - { - DCMSEG_ERROR("Rows is not set correctly (0)"); - fail = OFTrue; - } - if (cols == 0) - { - DCMSEG_ERROR("Columns is not set correctly (0)"); - fail = OFTrue; - } - - if (fail) - return EC_InvalidValue; - - return EC_Normal; -} + if (numFrames < 0) + { + DCMSEG_ERROR("Number of Frames must be greater than 0"); + fail = OFTrue; + } + else + { + numberOfFrames = OFstatic_cast(Uint16, numFrames); + } + } + Uint16 depth = 0; + if (m_SegmentationType == DcmSegTypes::ST_BINARY) + depth = 1; + else + depth = 8; + + if (allocated != depth) + { + DCMSEG_WARN("Bits Allocated is not set correctly (" + << allocated << ", ignored), assuming value " << depth << " as required for " + << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); + allocated = depth; + } + if (stored != depth) + { + DCMSEG_WARN("Bits Stored is not set correctly (" + << stored << ", ignored), assuming value " << depth << " as required for " + << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); + stored = depth; + } + if (high != depth - 1) + { + DCMSEG_WARN("High Bit is not set correctly (" + << high << ", ignored), assuming value " << depth - 1 << " as required for " + << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects"); + high = depth - 1; + } + if (spp != 1) + { + DCMSEG_WARN("Samples per Pixel is not set correctly (" + << spp << ", ignored), assuming value 1 as required for segmentation objects"); + spp = 1; + } + if (pixelRep != 0) + { + DCMSEG_WARN("Pixel Representation is not set correctly (" + << pixelRep << ", ignored), assuming value 0 as required for segmentation objects"); + pixelRep = 0; + } + if (colorModel != "MONOCHROME2") + { + DCMSEG_WARN("Photometric Interpretation is not set correctly (ignored), assuming value MONOCHROME2 as required " + "for segmentation objects"); + colorModel = "MONOCHROME2"; + } + if (rows == 0) + { + DCMSEG_ERROR("Rows is not set correctly (0)"); + fail = OFTrue; + } + if (cols == 0) + { + DCMSEG_ERROR("Columns is not set correctly (0)"); + fail = OFTrue; + } + + if (fail) + return EC_InvalidValue; + + return EC_Normal; +} OFCondition DcmSegmentation::writeDataset(DcmItem& dataset) { - return write(dataset); + Uint8* pixData = NULL; + size_t pixDataLength; + OFCondition result = writeWithSeparatePixelData(dataset, pixData, pixDataLength); + if (result.good()) + { + if (pixDataLength <= 4294967294UL) + { + result = dataset.putAndInsertUint8Array(DCM_PixelData, pixData, OFstatic_cast(unsigned long, pixDataLength)); + } + else + { + result = FG_EC_PixelDataTooLarge; + } + delete[] pixData; + } + return result; } +OFCondition DcmSegmentation::writeConcatenation(ConcatenationCreator& cc) +{ + Uint8* pixData = NULL; + size_t pixDataLength = 0; + DcmItem* item = new DcmItem(); + if (!item) + return EC_MemoryExhausted; + OFCondition result = writeWithSeparatePixelData(*item, pixData, pixDataLength); + if (result.good()) + { + result = cc.setCfgInput(item, pixData, pixDataLength, OFTrue /* transfer ownership */); + } + return result; +} OFCondition DcmSegmentation::writeMultiFrameFunctionalGroupsModule(DcmItem& dataset) { - Uint32 numFrames = DcmIODUtil::limitMaxFrames(m_Frames.size(), "More than 2147483647 frames provided, limiting Number of Frames to 2147483647"); - m_FG.setNumberOfFrames(numFrames); - OFCondition result = m_FG.write(dataset); - if (result.good()) - m_FGInterface.write(dataset); - return result; + Uint32 numFrames = DcmIODUtil::limitMaxFrames( + m_Frames.size(), "More than 2147483647 frames provided, limiting Number of Frames to 2147483647"); + m_FG.setNumberOfFrames(numFrames); + OFCondition result = m_FG.write(dataset); + if (result.good()) + m_FGInterface.write(dataset); + return result; } - OFCondition DcmSegmentation::writeMultiFrameDimensionModule(DcmItem& dataset) { - OFCondition result = m_DimensionModule.checkDimensions(&dataset); - if (result.good()) - { - result = m_DimensionModule.write(dataset); - } - return result; + OFCondition result = m_DimensionModule.checkDimensions(&dataset); + if (result.good()) + { + result = m_DimensionModule.write(dataset); + } + return result; } - -OFCondition DcmSegmentation::writeFractionalFrames(DcmItem& dataset) +OFCondition DcmSegmentation::writeFractionalFrames(Uint8* pixData, const Uint32 numFrames, const size_t pixDataLength) { - Uint32 numFrames = DcmIODUtil::limitMaxFrames(m_Frames.size(), "More than 2147483647 frames provided, will only write 2147483647"); - OFCondition result; - Uint16 rows,cols; - rows = cols = 0; - getImagePixel().getRows(rows); - getImagePixel().getColumns(cols); - size_t numBytes = 0; - result = getTotalBytesRequired(rows, cols, numFrames, numBytes); - if (result.bad()) return result; - if (numBytes >= 4294967295UL) - { - DCMSEG_ERROR("Cannot store Segmentation objects with more than 4 GB pixel data (compression for writing not supported)"); - return EC_TooManyBytesRequested; - } - Uint8* pixdata = new Uint8[numBytes]; - OFVector::iterator it = m_Frames.begin(); - // Just copy bytes for each frame as is - for (size_t count = 0; it != m_Frames.end(); count++) - { - memcpy(pixdata + count*(*it)->length, (*it)->pixData, (*it)->length); - it++; - } - dataset.putAndInsertUint8Array(DCM_PixelData, pixdata, OFstatic_cast(unsigned long, numBytes), OFTrue); - delete[] pixdata; - return result; + OFVector::iterator it = m_Frames.begin(); + // Just copy bytes for each frame as is + for (size_t count = 0; it != m_Frames.end(); count++) + { + memcpy(pixData + count * (*it)->length, (*it)->pixData, (*it)->length); + it++; + } + return EC_Normal; } - -OFCondition DcmSegmentation::writeBinaryFrames(DcmItem& dataset) +OFCondition DcmSegmentation::writeBinaryFrames(Uint8* pixData, Uint16 rows, Uint16 cols, const size_t pixDataLength) { - Uint16 rows, cols; - rows = cols = 0; - Uint32 numFrames = 0; - numFrames = DcmIODUtil::limitMaxFrames(m_Frames.size(), "More than 2147483647 frames provided, will only write 2147483647"); - OFCondition result; - getImagePixel().getRows(rows); - getImagePixel().getColumns(cols); - size_t numBytes = 0; - result = getTotalBytesRequired(rows, cols, numFrames, numBytes); - if (result.bad()) return result; - if (numBytes >= 4294967295UL) - { - DCMSEG_ERROR("Cannot store Segmentation objects with more than 4 GB pixel data (compression for writing not supported)"); - return EC_TooManyBytesRequested; - } - // Holds the pixels for all frames. Each bit represents a pixel which is either - // 1 (part of segment) or 0 (not part of segment. All frames are directly - // concatenated, i.e. there are no unused bits between the frames. - Uint8* pixdata = new Uint8[numBytes]; - memset(pixdata, 0, numBytes); - - // Fill Pixel Data Element - concatFrames(m_Frames, pixdata, rows*cols); - result = dataset.putAndInsertUint8Array(DCM_PixelData, pixdata, OFstatic_cast(unsigned long, numBytes), OFTrue); - delete [] pixdata; - return result; -} + // Holds the pixels for all frames. Each bit represents a pixel which is either + // 1 (part of segment) or 0 (not part of segment. All frames are directly + // concatenated, i.e. there are no unused bits between the frames. + memset(pixData, 0, pixDataLength); + // Fill Pixel Data Element + concatFrames(m_Frames, pixData, rows * cols); + return EC_Normal; +} OFCondition DcmSegmentation::writeSegmentationImageModule(DcmItem& dataset) { - dataset.putAndInsertOFStringArray(DCM_ImageType, "DERIVED\\PRIMARY"); - - OFCondition result = m_ContentIdentificationMacro.write(dataset); - - /* Write hardcoded values */ - if (result.good()) - { - getImagePixel().setSamplesPerPixel(1); - getImagePixel().setPhotometricInterpretation("MONOCHROME2"); - getImagePixel().setPixelRepresentation(0); - - /* Write Bits Allocated/Stored, High Bit, Segmentation Fractional Type, - * Segmentation Type, Maximum Fractional Value - */ - switch (m_SegmentationType) - { - case DcmSegTypes::ST_BINARY: - { - getImagePixel().setBitsAllocated(1); - getImagePixel().setBitsStored(1); - getImagePixel().setHighBit(0); - dataset.putAndInsertOFStringArray(DCM_SegmentationType, "BINARY"); - break; - } - case DcmSegTypes::ST_FRACTIONAL: - { - getImagePixel().setBitsAllocated(8); - getImagePixel().setBitsStored(8); - getImagePixel().setHighBit(7); - dataset.putAndInsertOFStringArray(DCM_SegmentationType, "FRACTIONAL"); - if (m_SegmentationFractionalType == DcmSegTypes::SFT_OCCUPANCY) - { - dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "OCCUPANCY"); - } - else + dataset.putAndInsertOFStringArray(DCM_ImageType, "DERIVED\\PRIMARY"); + + OFCondition result = m_ContentIdentificationMacro.write(dataset); + + /* Write hardcoded values */ + if (result.good()) + { + getImagePixel().setSamplesPerPixel(1); + getImagePixel().setPhotometricInterpretation("MONOCHROME2"); + getImagePixel().setPixelRepresentation(0); + + /* Write Bits Allocated/Stored, High Bit, Segmentation Fractional Type, + * Segmentation Type, Maximum Fractional Value + */ + switch (m_SegmentationType) { - dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "PROBABILITY"); + case DcmSegTypes::ST_BINARY: + { + getImagePixel().setBitsAllocated(1); + getImagePixel().setBitsStored(1); + getImagePixel().setHighBit(0); + dataset.putAndInsertOFStringArray(DCM_SegmentationType, "BINARY"); + break; + } + case DcmSegTypes::ST_FRACTIONAL: + { + getImagePixel().setBitsAllocated(8); + getImagePixel().setBitsStored(8); + getImagePixel().setHighBit(7); + dataset.putAndInsertOFStringArray(DCM_SegmentationType, "FRACTIONAL"); + if (m_SegmentationFractionalType == DcmSegTypes::SFT_OCCUPANCY) + { + dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "OCCUPANCY"); + } + else + { + dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "PROBABILITY"); + } + // Maximum Fractional Value: Attribute is type 1C but "required if .. FRACTIONAL", i.e. write type 1 + DcmIODUtil::copyElementToDataset( + result, dataset, m_MaximumFractionalValue, "1", "1", "SegmentationImageModule"); + break; + } + case DcmSegTypes::ST_UNKNOWN: + { + DCMSEG_ERROR("Internal error, segmentation type not set"); + result = EC_InternalError; + break; + } } - // Maximum Fractional Value: Attribute is type 1C but "required if .. FRACTIONAL", i.e. write type 1 - DcmIODUtil::copyElementToDataset(result, dataset, m_MaximumFractionalValue, "1", "1", "SegmentationImageModule"); - break; - } - case DcmSegTypes::ST_UNKNOWN: - { DCMSEG_ERROR("Internal error, segmentation type not set"); - result = EC_InternalError; - break; - } - } - } - - /* Write segments */ - OFVector segmentItems; - if (result.good()) - { - OFVector::iterator it = m_Segments.begin(); - dataset.findAndDeleteElement(DCM_SegmentSequence); - for ( Uint16 itemCount = 0; (it != m_Segments.end()) && result.good(); itemCount++) - { - DcmItem* segmentItem = NULL; - dataset.findOrCreateSequenceItem(DCM_SegmentSequence, segmentItem, itemCount); - if (segmentItem) - { - result = (*it)->write(*segmentItem); - /* Insert segment number for the segment, starting from 1 and increasing monotonically. */ - if (result.good()) + } + + /* Write segments */ + OFVector segmentItems; + if (result.good()) + { + OFVector::iterator it = m_Segments.begin(); + dataset.findAndDeleteElement(DCM_SegmentSequence); + for (Uint16 itemCount = 0; (it != m_Segments.end()) && result.good(); itemCount++) { - segmentItem->putAndInsertUint16(DCM_SegmentNumber, itemCount+1); + DcmItem* segmentItem = NULL; + dataset.findOrCreateSequenceItem(DCM_SegmentSequence, segmentItem, itemCount); + if (segmentItem) + { + result = (*it)->write(*segmentItem); + /* Insert segment number for the segment, starting from 1 and increasing monotonically. */ + if (result.good()) + { + segmentItem->putAndInsertUint16(DCM_SegmentNumber, itemCount + 1); + } + } + else + { + DCMIOD_ERROR("Cannot create/get item in Segment Sequence (internal error)"); + result = EC_InternalError; + } + it++; } - } - else - { - DCMIOD_ERROR("Cannot create/get item in Segment Sequence (internal error)"); - result = EC_InternalError; - } - it++; - } - } - - /* Write frame pixel data */ - if (result.good()) - { - if (m_SegmentationType == DcmSegTypes::ST_BINARY) result = writeBinaryFrames(dataset); - else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL) result = writeFractionalFrames(dataset); - else result = SG_EC_UnknownSegmentationType; - } - - return result; + } + + return result; } // -- private helpers -- void DcmSegmentation::clearData() { - DcmSegmentation::IODImage::clearData(); - m_FG.clearData(); - m_FGInterface.clear(); - DcmIODUtil::freeContainer(m_Frames); - DcmIODUtil::freeContainer(m_Segments); - m_MaximumFractionalValue.clear(); - m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN; - m_SegmentationType = DcmSegTypes::ST_UNKNOWN; + DcmSegmentation::IODImage::clearData(); + m_FG.clearData(); + m_FGInterface.clear(); + DcmIODUtil::freeContainer(m_Frames); + DcmIODUtil::freeContainer(m_Segments); + m_MaximumFractionalValue.clear(); + m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN; + m_SegmentationType = DcmSegTypes::ST_UNKNOWN; } - OFBool DcmSegmentation::checkPixDataLength(DcmElement* pixelData, const Uint16 rows, const Uint16 cols, const Uint16& numberOfFrames) { - // Get actual length of pixel data in bytes - size_t length = pixelData->getLengthField(); - - // Find out how many bytes are needed - size_t bytesRequired = 0; - OFCondition result = getTotalBytesRequired(rows, cols, numberOfFrames, bytesRequired); - if (result.bad()) return OFFalse; - // Length found in Pixel Data element is always even - if (bytesRequired % 2 == 1) bytesRequired++; - /* Compare expected and actual length */ - if (length < bytesRequired) - { - DCMSEG_ERROR("Not enough bytes found in Pixel Data element. Found " << length << " bytes but " << bytesRequired << " bytes expected"); - return OFFalse; - } - else if (length > bytesRequired) - { - DCMSEG_WARN("Too many bytes found in Pixel Data element. Found " << length << " bytes but " << bytesRequired << " bytes expected"); + // Get actual length of pixel data in bytes + size_t length = pixelData->getLengthField(); + + // Find out how many bytes are needed + size_t bytesRequired = 0; + OFCondition result = getTotalBytesRequired(rows, cols, numberOfFrames, bytesRequired); + if (result.bad()) + return OFFalse; + // Length found in Pixel Data element is always even + if (bytesRequired % 2 == 1) + bytesRequired++; + /* Compare expected and actual length */ + if (length < bytesRequired) + { + DCMSEG_ERROR("Not enough bytes found in Pixel Data element. Found " << length << " bytes but " << bytesRequired + << " bytes expected"); + return OFFalse; + } + else if (length > bytesRequired) + { + DCMSEG_WARN("Too many bytes found in Pixel Data element. Found " << length << " bytes but " << bytesRequired + << " bytes expected"); + return OFTrue; + } + else + { + DCMSEG_TRACE("Found " << length << " bytes in Pixel Data element as expected"); + } return OFTrue; - } - else - { - DCMSEG_TRACE("Found " << length << " bytes in Pixel Data element as expected"); - } - return OFTrue; } - OFCondition DcmSegmentation::getTotalBytesRequired(const Uint16& rows, const Uint16& cols, const Uint32& numberOfFrames, size_t& bytesRequired) { - OFBool ok = OFStandard::safeMult(OFstatic_cast(size_t, rows), OFstatic_cast(size_t, cols), bytesRequired); - if (ok) OFStandard::safeMult(bytesRequired, OFstatic_cast(size_t, numberOfFrames), bytesRequired); - if (!ok) - { - DCMSEG_ERROR("Cannot compute number of bytes required for Pixel Data since size_t type is too small"); - return EC_TooManyBytesRequested; - } - - /* for binary, we only need one bit per pixel */ - size_t remainder = 0; - if (m_SegmentationType == DcmSegTypes::ST_BINARY) - { - // check whether the 1-bit pixels exactly fit into bytes - remainder = (OFstatic_cast(size_t, rows) * cols) % 8; - // number of bytes that work on an exact fit - bytesRequired = bytesRequired / 8; - // add one byte if we have a remainder - if (remainder > 0) - { - bytesRequired++; - } - } - return EC_Normal; -} + OFBool ok = OFStandard::safeMult(OFstatic_cast(size_t, rows), OFstatic_cast(size_t, cols), bytesRequired); + if (ok) + OFStandard::safeMult(bytesRequired, OFstatic_cast(size_t, numberOfFrames), bytesRequired); + if (!ok) + { + DCMSEG_ERROR("Cannot compute number of bytes required for Pixel Data since size_t type is too small"); + return EC_TooManyBytesRequested; + } + /* for binary, we only need one bit per pixel */ + size_t remainder = 0; + if (m_SegmentationType == DcmSegTypes::ST_BINARY) + { + // check whether the 1-bit pixels exactly fit into bytes + remainder = (OFstatic_cast(size_t, rows) * cols) % 8; + // number of bytes that work on an exact fit + bytesRequired = bytesRequired / 8; + // add one byte if we have a remainder + if (remainder > 0) + { + bytesRequired++; + } + } + return EC_Normal; +} -OFCondition DcmSegmentation::loadFile(DcmFileFormat& dcmff, - const OFString& filename, - DcmDataset*& dset) +OFCondition DcmSegmentation::loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset) { - dset = NULL; - OFCondition result = dcmff.loadFile(filename.c_str()); - if (result.bad()) - { - DCMSEG_ERROR("Could not load file " << filename << ": " << result.text()); + dset = NULL; + OFCondition result = dcmff.loadFile(filename.c_str()); + if (result.bad()) + { + DCMSEG_ERROR("Could not load file " << filename << ": " << result.text()); + return result; + } + dset = dcmff.getDataset(); + if (dset == NULL) + { + DCMSEG_ERROR("Could not load file " << filename << ": No dataset"); + return IOD_EC_InvalidObject; + } return result; - } - dset = dcmff.getDataset(); - if (dset == NULL) - { - DCMSEG_ERROR("Could not load file " << filename << ": No dataset"); - return IOD_EC_InvalidObject; - } - return result; } - OFCondition DcmSegmentation::readSegmentationFractionalType(DcmItem& item) { - m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN; - if (!item.tagExists(DCM_SegmentationFractionalType)) - { - return EC_TagNotFound; - } - DcmCodeString element(DCM_SegmentationFractionalType); - OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(item, element, getRules()->getByTag(DCM_SegmentationFractionalType)); - OFString str; - if (result.good()) - { - element.getOFStringArray(str); - m_SegmentationFractionalType = DcmSegTypes::OFString2FractionalType(str); - } - - if (m_SegmentationFractionalType == DcmSegTypes::SFT_UNKNOWN) - { - DCMSEG_ERROR("Invalid value for attribute Segmentation Fractional Type: " << str); - return EC_InvalidValue; - } - else - return EC_Normal; -} + m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN; + if (!item.tagExists(DCM_SegmentationFractionalType)) + { + return EC_TagNotFound; + } + DcmCodeString element(DCM_SegmentationFractionalType); + OFCondition result = DcmIODUtil::getAndCheckElementFromDataset( + item, element, getRules()->getByTag(DCM_SegmentationFractionalType)); + OFString str; + if (result.good()) + { + element.getOFStringArray(str); + m_SegmentationFractionalType = DcmSegTypes::OFString2FractionalType(str); + } + if (m_SegmentationFractionalType == DcmSegTypes::SFT_UNKNOWN) + { + DCMSEG_ERROR("Invalid value for attribute Segmentation Fractional Type: " << str); + return EC_InvalidValue; + } + else + return EC_Normal; +} OFCondition DcmSegmentation::readSegmentationType(DcmItem& item) { - m_SegmentationType = DcmSegTypes::ST_UNKNOWN; - if (!item.tagExists(DCM_SegmentationType)) - { - return EC_TagNotFound; - } - - DcmCodeString element(DCM_SegmentationType); - OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(item, element, getRules()->getByTag(DCM_SegmentationType)); - OFString str; - if (result.good()) - { - element.getOFStringArray(str); - m_SegmentationType = DcmSegTypes::OFString2Segtype(str); - } - - if (m_SegmentationType == DcmSegTypes::ST_UNKNOWN) - { - DCMSEG_ERROR("Invalid value for attribute Segmentation Type: " << str); - result = EC_InvalidValue; - } - - return result; -} + m_SegmentationType = DcmSegTypes::ST_UNKNOWN; + if (!item.tagExists(DCM_SegmentationType)) + { + return EC_TagNotFound; + } + DcmCodeString element(DCM_SegmentationType); + OFCondition result + = DcmIODUtil::getAndCheckElementFromDataset(item, element, getRules()->getByTag(DCM_SegmentationType)); + OFString str; + if (result.good()) + { + element.getOFStringArray(str); + m_SegmentationType = DcmSegTypes::OFString2Segtype(str); + } + + if (m_SegmentationType == DcmSegTypes::ST_UNKNOWN) + { + DCMSEG_ERROR("Invalid value for attribute Segmentation Type: " << str); + result = EC_InvalidValue; + } + + return result; +} // protected override of public base class function IODImagePixelModule& DcmSegmentation::getImagePixel() { - return *OFget >( &DcmSegmentation::IODImage::getImagePixel() ); + return *OFget >(&DcmSegmentation::IODImage::getImagePixel()); } - OFBool DcmSegmentation::check(const OFBool checkFGStructure) { - if (m_Frames.size() == 0) - { - DCMSEG_ERROR("No frame data available"); - return OFFalse; - } - if (m_Segments.size() == 0) - { - DCMSEG_ERROR("No segments defined"); - return OFFalse; - } - if (m_Segments.size() > m_Frames.size()) - { - DCMSEG_ERROR("There are more segments than frames defined"); - return OFFalse; - } - - if (checkFGStructure) - { - if (!m_FGInterface.check()) - return OFFalse; - } - - // Check rules around Frame of Reference - - // 1. If Derivation Image FG is not present, Frame of Reference is required. - OFBool frameOfRefRequired = OFFalse; - FGBase* group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_DERIVATIONIMAGE); - if (group == NULL) - { - // Derivation Image FG is not present, FoR is required - frameOfRefRequired = OFTrue; - } - else - { - // Derivation Image FG present, Frame of Reference is not required - frameOfRefRequired = OFFalse; - } - OFString frameOfRef; - getFrameOfReference().getFrameOfReferenceUID(frameOfRef); - if (frameOfRefRequired && frameOfRef.empty()) - { - DCMSEG_ERROR("Frame of Reference UID is not set for Segmentation but is required"); - return OFFalse; - } - - // 2. When a Frame of Reference UID is present the segment shall be specified - // within that coordinate system, using the Pixel Measures, Plane Position - // (Patient) and Plane Orientation (Patient) Functional Groups. - if (!frameOfRef.empty()) - { - // Check that each of above FGs is present. We do not check this for - // all frames since if it exists for one frame it must exist for all others. - // This is a general rule and applies for all FGs, so it is not checked here. - group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PIXELMEASURES); - if (!group) - { - DCMSEG_ERROR("Frame of Reference UID is present but Pixel Measures FG is missing"); - return OFFalse; - } - group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PLANEPOSPATIENT); - if (!group) - { - DCMSEG_ERROR("Frame of Reference UID is present but Plane Position (Patient) FG is missing"); - return OFFalse; - } - group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PLANEORIENTPATIENT); - if (!group) - { - DCMSEG_ERROR("Frame of Reference UID is present but Plane Orientation (Patient) FG is missing"); - return OFFalse; - } - } - // Another condition cannot be checked since we do not have access to the - // datasets of the source images: - // 3. If FoR is present but not the same in images this segmentation applies to, - // (those in Derivation Image FG), each pixel of the segmentation shall - // correspond to a pixel in a referenced image (i.e. they must share the same - // size and resolution). - - return OFTrue; -} + if (m_Frames.size() == 0) + { + DCMSEG_ERROR("No frame data available"); + return OFFalse; + } + if (m_Segments.size() == 0) + { + DCMSEG_ERROR("No segments defined"); + return OFFalse; + } + if (m_Segments.size() > m_Frames.size()) + { + DCMSEG_ERROR("There are more segments than frames defined"); + return OFFalse; + } + if (checkFGStructure) + { + if (!m_FGInterface.check()) + return OFFalse; + } -OFCondition DcmSegmentation::decompress(DcmDataset& dset) -{ - DcmXfer xfer = dset.getOriginalXfer(); - OFCondition result; - // If the original transfer syntax could have been lossy, print warning - if (dset.hasRepresentation(EXS_LittleEndianExplicit, NULL)) - { - if ( xfer.isEncapsulated() && (xfer.getXfer() != EXS_RLELossless) && (xfer.getXfer() != EXS_DeflatedLittleEndianExplicit) ) + // Check rules around Frame of Reference + + // 1. If Derivation Image FG is not present, Frame of Reference is required. + OFBool frameOfRefRequired = OFFalse; + FGBase* group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_DERIVATIONIMAGE); + if (group == NULL) { - DCMSEG_WARN("Dataset has been compressed using a (possibly) lossy compression scheme (ignored)"); + // Derivation Image FG is not present, FoR is required + frameOfRefRequired = OFTrue; } - } - // If the original transfer is encapsulated and we do not already have an uncompressed version, decompress or reject the file - else if (xfer.isEncapsulated()) - { - // RLE compression is fine (truly lossless). Deflated is handled internally by DCMTK. - if (xfer.getXfer() == EXS_RLELossless) + else { - DCMSEG_DEBUG("DICOM file is RLE-compressed, converting to uncompressed transfer syntax first"); - result = DcmIODUtil::decompress(dset); + // Derivation Image FG present, Frame of Reference is not required + frameOfRefRequired = OFFalse; } - else // We do not accept any transfer syntax that could be lossy compressed + OFString frameOfRef; + getFrameOfReference().getFrameOfReferenceUID(frameOfRef); + if (frameOfRefRequired && frameOfRef.empty()) { - DCMSEG_ERROR("Transfer syntax " << DcmXfer(xfer).getXferName() << " uses lossy compression, not supported for Segmentation objects!"); - result = IOD_EC_CannotDecompress; + DCMSEG_ERROR("Frame of Reference UID is not set for Segmentation but is required"); + return OFFalse; } - } - return result; -} + // 2. When a Frame of Reference UID is present the segment shall be specified + // within that coordinate system, using the Pixel Measures, Plane Position + // (Patient) and Plane Orientation (Patient) Functional Groups. + if (!frameOfRef.empty()) + { + // Check that each of above FGs is present. We do not check this for + // all frames since if it exists for one frame it must exist for all others. + // This is a general rule and applies for all FGs, so it is not checked here. + group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PIXELMEASURES); + if (!group) + { + DCMSEG_ERROR("Frame of Reference UID is present but Pixel Measures FG is missing"); + return OFFalse; + } + group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PLANEPOSPATIENT); + if (!group) + { + DCMSEG_ERROR("Frame of Reference UID is present but Plane Position (Patient) FG is missing"); + return OFFalse; + } + group = m_FGInterface.get(OFstatic_cast(Uint32, 0), DcmFGTypes::EFG_PLANEORIENTPATIENT); + if (!group) + { + DCMSEG_ERROR("Frame of Reference UID is present but Plane Orientation (Patient) FG is missing"); + return OFFalse; + } + } + // Another condition cannot be checked since we do not have access to the + // datasets of the source images: + // 3. If FoR is present but not the same in images this segmentation applies to, + // (those in Derivation Image FG), each pixel of the segmentation shall + // correspond to a pixel in a referenced image (i.e. they must share the same + // size and resolution). + + return OFTrue; +} -OFCondition DcmSegmentation::extractFrames(Uint8* pixData, - const size_t numFrames, - const size_t bitsPerFrame, - OFVector< DcmIODTypes::Frame* >& results) +OFCondition DcmSegmentation::decompress(DcmDataset& dset) { - // Will hold the bit position (0-7) that the current frame starts from. The - // first frame will always start at bit 0. - Uint8 bitShift = 0; - // Compute length in bytes we need to consider for each frame. - size_t frameLengthBytes = bitsPerFrame / 8; - // If the number of bits is not dividable by 8, we need part of an extra - // byte in the end. Since we like to set the unused bits to 0 in such a last - // byte to 0, remember the number. - size_t overlapBits = (8 - (bitsPerFrame % 8)) % 8; - // Add an extra byte if we we fill a partial byte in the end - if (overlapBits != 0) frameLengthBytes++; - // Points to current reading position within pixData - Uint8* readPos = pixData; - // Loop over each frame and copy it to Frame structures - for (size_t f = 0; f < numFrames; f++) - { - // Create frame with correct length and copy 1:1 from pixel data - DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); - frame->length = frameLengthBytes; - frame->pixData = new Uint8[frameLengthBytes]; - if (!frame->pixData) + DcmXfer xfer = dset.getOriginalXfer(); + OFCondition result; + // If the original transfer syntax could have been lossy, print warning + if (dset.hasRepresentation(EXS_LittleEndianExplicit, NULL)) { - return EC_MemoryExhausted; - } - memcpy(frame->pixData, readPos, frame->length); - // If we have been copying too much, i.e the first bits of the frame - // actually belong to the former frame, shift the whole frame this amount - // of bits to the left in order to shift the superfluous bits out, i.e. - // make frame start at byte boundary. - if (bitShift > 0) - { - DcmSegUtils::alignFrameOnByteBoundary(frame->pixData, frame->length, 8-bitShift); - } - // Adapt last byte by masking out unused bits (i.e. those belonging to next frame). - // A reader should ignore those unused bits anyway. - frame->pixData[frame->length-1] = (frame->pixData[frame->length-1] << (overlapBits)) >> (overlapBits); - // Store frame - results.push_back(frame); - // Compute the bitshift created by this frame - bitShift = ( 8- ((f+1) * bitsPerFrame) % 8 ) % 8; - // If the previous byte read has not been used completely, i.e. it contains - // also bytes of the next frame, rewind read position to the previous byte - // that was partially read. Otherwise skip to the next full byte. - if (bitShift > 0) - { - readPos = readPos + frame->length - 1; + if (xfer.isEncapsulated() && (xfer.getXfer() != EXS_RLELossless) + && (xfer.getXfer() != EXS_DeflatedLittleEndianExplicit)) + { + DCMSEG_WARN("Dataset has been compressed using a (possibly) lossy compression scheme (ignored)"); + } } - else + // If the original transfer is encapsulated and we do not already have an uncompressed version, decompress or reject + // the file + else if (xfer.isEncapsulated()) { - readPos = readPos + frame->length; + // RLE compression is fine (truly lossless). Deflated is handled internally by DCMTK. + if (xfer.getXfer() == EXS_RLELossless) + { + DCMSEG_DEBUG("DICOM file is RLE-compressed, converting to uncompressed transfer syntax first"); + result = DcmIODUtil::decompress(dset); + } + else // We do not accept any transfer syntax that could be lossy compressed + { + DCMSEG_ERROR("Transfer syntax " << DcmXfer(xfer).getXferName() + << " uses lossy compression, not supported for Segmentation objects!"); + result = IOD_EC_CannotDecompress; + } } - } - return EC_Normal; + return result; } - -void DcmSegmentation::concatFrames(OFVector< DcmIODTypes::Frame* > frames, - Uint8* pixData, - const size_t bitsPerFrame) +void DcmSegmentation::concatFrames(OFVector frames, Uint8* pixData, const size_t bitsPerFrame) { - // Writing position within the pixData memory - Uint8 *writePos = pixData; - OFVector::iterator frame = frames.begin(); - Uint8 freeBits = 0; - Uint8 firstByte = 0; - // Iterate over frames and copy each to pixData memory - for (size_t f = 0; frame != frames.end(); f++) - { - DCMSEG_DEBUG("Packing segmentation frame #" << f+1 << "/" << frames.size()); - // Backup first byte of the destination since it may contain bits of the - // previous frame; mask out those bits not belonging to previous frame. - // This will potentially create some empty bits on the left of the byte, - // that the current frame can use to store the its own first bits. - firstByte = (writePos[0] << freeBits) >> freeBits; - memcpy(writePos, (*frame)->pixData, (*frame)->length); - // If the previous frame left over some unused bits, shift the current frame - // that number of bits to the left, and restore the original bits of the - // previous frame that are overwritten by the shifting operation. - if (freeBits > 0) + // Writing position within the pixData memory + Uint8* writePos = pixData; + OFVector::iterator frame = frames.begin(); + Uint8 freeBits = 0; + Uint8 firstByte = 0; + // Iterate over frames and copy each to pixData memory + for (size_t f = 0; frame != frames.end(); f++) { - DcmSegUtils::alignFrameOnBitPosition(writePos, (*frame)->length, 8-freeBits); - writePos[0] |= firstByte; + DCMSEG_DEBUG("Packing segmentation frame #" << f + 1 << "/" << frames.size()); + // Backup first byte of the destination since it may contain bits of the + // previous frame; mask out those bits not belonging to previous frame. + // This will potentially create some empty bits on the left of the byte, + // that the current frame can use to store the its own first bits. + firstByte = (writePos[0] << freeBits) >> freeBits; + memcpy(writePos, (*frame)->pixData, (*frame)->length); + // If the previous frame left over some unused bits, shift the current frame + // that number of bits to the left, and restore the original bits of the + // previous frame that are overwritten by the shifting operation. + if (freeBits > 0) + { + DcmSegUtils::alignFrameOnBitPosition(writePos, (*frame)->length, 8 - freeBits); + writePos[0] |= firstByte; + } + // Compute free bits left over from this frame in the previous byte written + freeBits = (8 - (((f + 1) * bitsPerFrame) % 8)) % 8; + // If we have free bits, the previous byte written to will be the first byte + // we write to for the next frame. Otherwise start with a fresh destination + // byte. + if (freeBits > 0) + { + writePos = writePos + (*frame)->length - 1; + } + else + { + writePos = writePos + (*frame)->length; + } + // Next frame + frame++; } - // Compute free bits left over from this frame in the previous byte written - freeBits = (8 - (( (f+1) * bitsPerFrame ) % 8)) % 8; - // If we have free bits, the previous byte written to will be the first byte - // we write to for the next frame. Otherwise start with a fresh destination - // byte. + // Through shifting we can have non-zero bits within the unused bits of the + // last byte. Fill them with zeros (though not required by the standard). if (freeBits > 0) { - writePos = writePos + (*frame)->length - 1; + *writePos = (*writePos >> freeBits) << freeBits; } - else - { - writePos = writePos + (*frame)->length; - } - // Next frame - frame++; - } - // Through shifting we can have non-zero bits within the unused bits of the - // last byte. Fill them with zeros (though not required by the standard). - if (freeBits > 0) - { - *writePos = (*writePos >> freeBits) << freeBits; - } } diff --git a/dcmseg/libsrc/segment.cc b/dcmseg/libsrc/segment.cc index de0ef59f..8db7b5fc 100644 --- a/dcmseg/libsrc/segment.cc +++ b/dcmseg/libsrc/segment.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2017, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -18,12 +18,13 @@ * Purpose: Class representing a Segment from the Segment Ident. Sequence * */ + #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmseg/segdoc.h" #include "dcmtk/dcmseg/segment.h" #include "dcmtk/dcmseg/segtypes.h" -#include "dcmtk/dcmseg/segdoc.h" - OFCondition DcmSegment::create(DcmSegment*& segment, const OFString& segmentLabel, @@ -33,364 +34,320 @@ OFCondition DcmSegment::create(DcmSegment*& segment, const OFString& algoName) { - segment = new DcmSegment(); - if (segment == NULL) - return EC_MemoryExhausted; + segment = new DcmSegment(); + if (segment == NULL) + return EC_MemoryExhausted; - OFCondition result = segment->setSegmentLabel(segmentLabel, OFTrue /* check value */); + OFCondition result = segment->setSegmentLabel(segmentLabel, OFTrue /* check value */); - if (result.good()) - { - segment->m_SegmentDescription.getSegmentedPropertyCategoryCode() = segmentedPropertyCategory; - result = segment->m_SegmentDescription.getSegmentedPropertyCategoryCode().check(); - } - - if (result.good()) - { - segment->m_SegmentDescription.getSegmentedPropertyTypeCode() = segmentedPropertyType; - result = segment->getSegmentedPropertyTypeCode().check(); - } + if (result.good()) + { + segment->m_SegmentDescription.getSegmentedPropertyCategoryCode() = segmentedPropertyCategory; + result = segment->m_SegmentDescription.getSegmentedPropertyCategoryCode().check(); + } + if (result.good()) + { + segment->m_SegmentDescription.getSegmentedPropertyTypeCode() = segmentedPropertyType; + result = segment->getSegmentedPropertyTypeCode().check(); + } - if (result.good()) - { - result = segment->setSegmentAlgorithm(algoType, algoName, OFTrue); - } + if (result.good()) + { + result = segment->setSegmentAlgorithm(algoType, algoName, OFTrue); + } - if ( result.bad() ) - { - delete segment; - segment = NULL; - } + if (result.bad()) + { + delete segment; + segment = NULL; + } - return result; + return result; } - - -OFCondition DcmSegment::read(DcmItem& item, - const OFBool clearOldData) +OFCondition DcmSegment::read(DcmItem& item, const OFBool clearOldData) { - if (clearOldData) - clearData(); - - m_SegmentDescription.read(item); - DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName)); - - DcmIODUtil::readSingleItem( - item, - DCM_SegmentationAlgorithmIdentificationSequence, - m_SegmentationAlgorithmIdentification, - "3", - "Segmentation Image Module"); - - DcmIODUtil::getAndCheckElementFromDataset(item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue)); - DcmIODUtil::getAndCheckElementFromDataset(item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue)); - DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID)); - DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID)); - - return EC_Normal; + if (clearOldData) + clearData(); + + m_SegmentDescription.read(item); + DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName)); + + DcmIODUtil::readSingleItem(item, + DCM_SegmentationAlgorithmIdentificationSequence, + m_SegmentationAlgorithmIdentification, + "3", + "Segmentation Image Module"); + + DcmIODUtil::getAndCheckElementFromDataset( + item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue)); + DcmIODUtil::getAndCheckElementFromDataset( + item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue)); + DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID)); + DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID)); + + return EC_Normal; } - OFCondition DcmSegment::write(DcmItem& item) { - OFCondition result; - result = m_SegmentDescription.write(item); - DcmIODUtil::copyElementToDataset(result, item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName)); - - if (result.good() && m_SegmentationAlgorithmIdentification.check(OFTrue /* quiet */).good()) - { - DcmIODUtil::writeSingleItem( - result, - DCM_SegmentationAlgorithmIdentificationSequence, - m_SegmentationAlgorithmIdentification, - item, - "3", - "Segmentation Image Module"); - } - - DcmIODUtil::copyElementToDataset(result, item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue)); - DcmIODUtil::copyElementToDataset(result, item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue)); - DcmIODUtil::copyElementToDataset(result, item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID)); - DcmIODUtil::copyElementToDataset(result, item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID)); - - return result; -} + OFCondition result; + result = m_SegmentDescription.write(item); + DcmIODUtil::copyElementToDataset(result, item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName)); + if (result.good() && m_SegmentationAlgorithmIdentification.check(OFTrue /* quiet */).good()) + { + DcmIODUtil::writeSingleItem(result, + DCM_SegmentationAlgorithmIdentificationSequence, + m_SegmentationAlgorithmIdentification, + item, + "3", + "Segmentation Image Module"); + } + DcmIODUtil::copyElementToDataset( + result, item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue)); + DcmIODUtil::copyElementToDataset( + result, item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue)); + DcmIODUtil::copyElementToDataset(result, item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID)); + DcmIODUtil::copyElementToDataset(result, item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID)); + + return result; +} void DcmSegment::clearData() { - m_SegmentDescription.clearData(); - m_SegmentAlgorithmName.clear(); - m_SegmentationAlgorithmIdentification.clearData(); - m_RecommendedDisplayGrayscaleValue.clear(); - m_RecommendedDisplayCIELabValue.clear(); - m_TrackingID.clear(); - m_TrackingUID.clear(); + m_SegmentDescription.clearData(); + m_SegmentAlgorithmName.clear(); + m_SegmentationAlgorithmIdentification.clearData(); + m_RecommendedDisplayGrayscaleValue.clear(); + m_RecommendedDisplayCIELabValue.clear(); + m_TrackingID.clear(); + m_TrackingUID.clear(); } - - DcmSegment::~DcmSegment() { - clearData(); + clearData(); } - // protected default constructor -DcmSegment::DcmSegment() : - m_SegmentationDoc(NULL), - m_SegmentDescription(), - m_SegmentAlgorithmName(DCM_SegmentAlgorithmName), - m_SegmentationAlgorithmIdentification(), - m_RecommendedDisplayGrayscaleValue(DCM_RecommendedDisplayGrayscaleValue), - m_RecommendedDisplayCIELabValue(DCM_RecommendedDisplayCIELabValue), - m_TrackingID(DCM_TrackingID), - m_TrackingUID(DCM_TrackingUID), - m_Rules() +DcmSegment::DcmSegment() + : m_SegmentationDoc(NULL) + , m_SegmentDescription() + , m_SegmentAlgorithmName(DCM_SegmentAlgorithmName) + , m_SegmentationAlgorithmIdentification() + , m_RecommendedDisplayGrayscaleValue(DCM_RecommendedDisplayGrayscaleValue) + , m_RecommendedDisplayCIELabValue(DCM_RecommendedDisplayCIELabValue) + , m_TrackingID(DCM_TrackingID) + , m_TrackingUID(DCM_TrackingUID) + , m_Rules() { - initIODRules(); + initIODRules(); } - void DcmSegment::initIODRules() { - m_Rules.addRule(new IODRule(DCM_SegmentAlgorithmName, "1","1C","SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules.addRule(new IODRule(DCM_RecommendedDisplayGrayscaleValue, "1","3","SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules.addRule(new IODRule(DCM_RecommendedDisplayCIELabValue, "3","3","SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules.addRule(new IODRule(DCM_TrackingID, "1","1C","SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); - m_Rules.addRule(new IODRule(DCM_TrackingUID, "1","1C","SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules.addRule(new IODRule(DCM_SegmentAlgorithmName, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules.addRule( + new IODRule(DCM_RecommendedDisplayGrayscaleValue, "1", "3", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules.addRule( + new IODRule(DCM_RecommendedDisplayCIELabValue, "3", "3", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), + OFTrue); + m_Rules.addRule(new IODRule(DCM_TrackingID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules.addRule(new IODRule(DCM_TrackingUID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue); } - // -------------- getters -------------------- unsigned int DcmSegment::getSegmentNumber() { - unsigned int value = 0; - if (m_SegmentationDoc != NULL) - { - m_SegmentationDoc->getSegmentNumber(this, value); - } - return value; + unsigned int value = 0; + if (m_SegmentationDoc != NULL) + { + m_SegmentationDoc->getSegmentNumber(this, value); + } + return value; } - -OFCondition DcmSegment::getSegmentLabel(OFString& value, - const signed long pos) +OFCondition DcmSegment::getSegmentLabel(OFString& value, const signed long pos) { - return m_SegmentDescription.getSegmentLabel(value, pos); + return m_SegmentDescription.getSegmentLabel(value, pos); } - -OFCondition DcmSegment::getSegmentDescription(OFString& value, - const signed long pos) +OFCondition DcmSegment::getSegmentDescription(OFString& value, const signed long pos) { - return m_SegmentDescription.getSegmentDescription(value, pos); + return m_SegmentDescription.getSegmentDescription(value, pos); } - DcmSegTypes::E_SegmentAlgoType DcmSegment::getSegmentAlgorithmType() { - return m_SegmentDescription.getSegmentAlgorithmType(); + return m_SegmentDescription.getSegmentAlgorithmType(); } -OFCondition DcmSegment::getSegmentAlgorithmName(OFString& value, - const signed long pos) +OFCondition DcmSegment::getSegmentAlgorithmName(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_SegmentAlgorithmName, value, pos); + return DcmIODUtil::getStringValueFromElement(m_SegmentAlgorithmName, value, pos); } - GeneralAnatomyMacro& DcmSegment::getGeneralAnatomyCode() { - return m_SegmentDescription.getGeneralAnatomyCode(); + return m_SegmentDescription.getGeneralAnatomyCode(); } - AlgorithmIdentificationMacro& DcmSegment::getSegmentationAlgorithmIdentification() { - return m_SegmentationAlgorithmIdentification; + return m_SegmentationAlgorithmIdentification; } - CodeSequenceMacro& DcmSegment::getSegmentedPropertyCategoryCode() { - return m_SegmentDescription.getSegmentedPropertyCategoryCode(); + return m_SegmentDescription.getSegmentedPropertyCategoryCode(); } - CodeSequenceMacro& DcmSegment::getSegmentedPropertyTypeCode() { - return m_SegmentDescription.getSegmentedPropertyTypeCode(); + return m_SegmentDescription.getSegmentedPropertyTypeCode(); } - -OFVector< CodeSequenceMacro* >& DcmSegment::getSegmentedPropertyTypeModifierCode() +OFVector& DcmSegment::getSegmentedPropertyTypeModifierCode() { - return m_SegmentDescription.getSegmentedPropertyTypeModifier(); + return m_SegmentDescription.getSegmentedPropertyTypeModifier(); } - - -OFCondition DcmSegment::getRecommendedDisplayGrayscaleValue(Uint16& value, - const unsigned long pos) +OFCondition DcmSegment::getRecommendedDisplayGrayscaleValue(Uint16& value, const unsigned long pos) { - return m_RecommendedDisplayGrayscaleValue.getUint16(value, pos); + return m_RecommendedDisplayGrayscaleValue.getUint16(value, pos); } - -OFCondition DcmSegment::getRecommendedDisplayCIELabValue(Uint16& L, - Uint16& a, - Uint16& b) +OFCondition DcmSegment::getRecommendedDisplayCIELabValue(Uint16& L, Uint16& a, Uint16& b) { - OFCondition result = m_RecommendedDisplayCIELabValue.getUint16(L, 0); - if (result.good()) - result = m_RecommendedDisplayCIELabValue.getUint16(a, 1); + OFCondition result = m_RecommendedDisplayCIELabValue.getUint16(L, 0); + if (result.good()) + result = m_RecommendedDisplayCIELabValue.getUint16(a, 1); - if (result.good()) - result = m_RecommendedDisplayCIELabValue.getUint16(b, 2); + if (result.good()) + result = m_RecommendedDisplayCIELabValue.getUint16(b, 2); - return result; + return result; } - -OFCondition DcmSegment::getTrackingID(OFString& value, - const signed long pos) +OFCondition DcmSegment::getTrackingID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_TrackingID, value, pos); + return DcmIODUtil::getStringValueFromElement(m_TrackingID, value, pos); } - -OFCondition DcmSegment::getTrackingUID(OFString& value, - const signed long pos) +OFCondition DcmSegment::getTrackingUID(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_TrackingUID, value, pos); + return DcmIODUtil::getStringValueFromElement(m_TrackingUID, value, pos); } - // -------------- setters -------------------- - -OFCondition DcmSegment::setSegmentLabel(const OFString& value, - const OFBool checkValue) +OFCondition DcmSegment::setSegmentLabel(const OFString& value, const OFBool checkValue) { - return m_SegmentDescription.setSegmentLabel(value, checkValue); + return m_SegmentDescription.setSegmentLabel(value, checkValue); } - -OFCondition DcmSegment::setSegmentDescription(const OFString& value, - const OFBool checkValue) +OFCondition DcmSegment::setSegmentDescription(const OFString& value, const OFBool checkValue) { - return m_SegmentDescription.setSegmentDescription(value, checkValue); + return m_SegmentDescription.setSegmentDescription(value, checkValue); } - OFCondition DcmSegment::setSegmentAlgorithm(const DcmSegTypes::E_SegmentAlgoType algoType, const OFString& algoName, const OFBool checkValue) { - if (checkValue && algoType == DcmSegTypes::SAT_UNKNOWN) - { - DCMSEG_ERROR("Algorithm type must be initialized to a valid value"); - return EC_InvalidValue; - } - - OFCondition result; - // Set algorithm name if algorithm type is not manual (otherwise do not set it at all) - if (algoType != DcmSegTypes::SAT_MANUAL) - { - if ( checkValue && algoName.empty() ) + if (checkValue && algoType == DcmSegTypes::SAT_UNKNOWN) + { + DCMSEG_ERROR("Algorithm type must be initialized to a valid value"); + return EC_InvalidValue; + } + + OFCondition result; + // Set algorithm name if algorithm type is not manual (otherwise do not set it at all) + if (algoType != DcmSegTypes::SAT_MANUAL) { - DCMSEG_ERROR("Algorithm name must be provided if Algorithm Type is not 'MANUAL'"); - return EC_MissingValue; + if (checkValue && algoName.empty()) + { + DCMSEG_ERROR("Algorithm name must be provided if Algorithm Type is not 'MANUAL'"); + return EC_MissingValue; + } + if (!algoName.empty()) + { + result = (checkValue) ? DcmLongString::checkStringValue(algoName, "1") : EC_Normal; + if (result.good()) + { + result = m_SegmentAlgorithmName.putOFStringArray(algoName); + } + } } - if (!algoName.empty()) + // Set algorithm type + if (result.good()) { - result = (checkValue) ? DcmLongString::checkStringValue(algoName, "1") : EC_Normal; - if (result.good()) - { - result = m_SegmentAlgorithmName.putOFStringArray(algoName); - } + result = m_SegmentDescription.setSegmentAlgorithmType(algoType); } - } - // Set algorithm type - if (result.good()) - { - result = m_SegmentDescription.setSegmentAlgorithmType(algoType); - } - return result; + return result; } - OFCondition DcmSegment::setSegmentationAlgorithmIdentification(const AlgorithmIdentificationMacro& value, const OFBool checkValue) { - m_SegmentationAlgorithmIdentification = value; - OFCondition result; - if (checkValue) - { - result = m_SegmentationAlgorithmIdentification.check(); - } - - if (result.bad()) - { - m_SegmentationAlgorithmIdentification.clearData(); - } + m_SegmentationAlgorithmIdentification = value; + OFCondition result; + if (checkValue) + { + result = m_SegmentationAlgorithmIdentification.check(); + } - return result; -} + if (result.bad()) + { + m_SegmentationAlgorithmIdentification.clearData(); + } + return result; +} -OFCondition DcmSegment::setRecommendedDisplayGrayscaleValue(const Uint16 value, - const OFBool) +OFCondition DcmSegment::setRecommendedDisplayGrayscaleValue(const Uint16 value, const OFBool) { - return m_RecommendedDisplayGrayscaleValue.putUint16(value, 0); + return m_RecommendedDisplayGrayscaleValue.putUint16(value, 0); } - -OFCondition DcmSegment::setRecommendedDisplayCIELabValue(const Uint16 r, - const Uint16 g, - const Uint16 b, - const OFBool) +OFCondition DcmSegment::setRecommendedDisplayCIELabValue(const Uint16 r, const Uint16 g, const Uint16 b, const OFBool) { - OFCondition result = m_RecommendedDisplayCIELabValue.putUint16(r, 0); - if (result.good()) - result = m_RecommendedDisplayCIELabValue.putUint16(g, 1); - if (result.good()) - result = m_RecommendedDisplayCIELabValue.putUint16(b, 2); - return result; + OFCondition result = m_RecommendedDisplayCIELabValue.putUint16(r, 0); + if (result.good()) + result = m_RecommendedDisplayCIELabValue.putUint16(g, 1); + if (result.good()) + result = m_RecommendedDisplayCIELabValue.putUint16(b, 2); + return result; } - -OFCondition DcmSegment::setTrackingID(const OFString& value, - const OFBool checkValue) +OFCondition DcmSegment::setTrackingID(const OFString& value, const OFBool checkValue) { - // avoid compile warning on unused variable - (void)checkValue; - return m_TrackingID.putOFStringArray(value); + // avoid compile warning on unused variable + (void)checkValue; + return m_TrackingID.putOFStringArray(value); } - -OFCondition DcmSegment::setTrackingUID(const OFString& value, - const OFBool checkValue) +OFCondition DcmSegment::setTrackingUID(const OFString& value, const OFBool checkValue) { - OFCondition result; - if (checkValue) - { - result = DcmUniqueIdentifier::checkStringValue(value, "1"); - } - if (result.good()) - { - result = m_TrackingUID.putOFStringArray(value); - } - return result; + OFCondition result; + if (checkValue) + { + result = DcmUniqueIdentifier::checkStringValue(value, "1"); + } + if (result.good()) + { + result = m_TrackingUID.putOFStringArray(value); + } + return result; } - void DcmSegment::referenceSegmentationDoc(DcmSegmentation* doc) { - this->m_SegmentationDoc = doc; + this->m_SegmentationDoc = doc; } diff --git a/dcmseg/libsrc/segtypes.cc b/dcmseg/libsrc/segtypes.cc index 43dbf19a..dd1aacce 100644 --- a/dcmseg/libsrc/segtypes.cc +++ b/dcmseg/libsrc/segtypes.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2016, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,9 +20,10 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/dcmdata/dcerror.h" -#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmseg/segtypes.h" OFLogger DCM_dcmsegLogger = OFLog::getLogger("dcmtk.dcmseg"); @@ -32,327 +33,309 @@ OFLogger DCM_dcmsegLogger = OFLog::getLogger("dcmtk.dcmseg"); *---------------------------------*/ // conditions -makeOFConditionConst(SG_EC_MaxSegmentsReached, OFM_dcmseg, 1, OF_error, "Maximum Number of Functional Groups reached"); -makeOFConditionConst(SG_EC_NoSuchSegment, OFM_dcmseg, 2, OF_error, "No such segment"); -makeOFConditionConst(SG_EC_UnknownSegmentationType, OFM_dcmseg, 3, OF_error, "Unknown Segmentation Type"); -makeOFConditionConst(SG_EC_InvalidValue, OFM_dcmseg, 4, OF_error, "Invalid value for Segmentation SOP Class"); -makeOFConditionConst(SG_EC_NotEnoughData, OFM_dcmseg, 5, OF_error, "Not enough data"); - +makeOFConditionConst(SG_EC_MaxSegmentsReached, OFM_dcmseg, 1, OF_error, "Maximum Number of Functional Groups reached"); +makeOFConditionConst(SG_EC_NoSuchSegment, OFM_dcmseg, 2, OF_error, "No such segment"); +makeOFConditionConst(SG_EC_UnknownSegmentationType, OFM_dcmseg, 3, OF_error, "Unknown Segmentation Type"); +makeOFConditionConst(SG_EC_InvalidValue, OFM_dcmseg, 4, OF_error, "Invalid value for Segmentation SOP Class"); +makeOFConditionConst(SG_EC_NotEnoughData, OFM_dcmseg, 5, OF_error, "Not enough data"); DcmSegTypes::E_SegmentationType DcmSegTypes::OFString2Segtype(const OFString& value) { - if (value == "BINARY") - return DcmSegTypes::ST_BINARY; - if (value == "FRACTIONAL") - return DcmSegTypes::ST_FRACTIONAL; - else - return DcmSegTypes::ST_UNKNOWN; + if (value == "BINARY") + return DcmSegTypes::ST_BINARY; + if (value == "FRACTIONAL") + return DcmSegTypes::ST_FRACTIONAL; + else + return DcmSegTypes::ST_UNKNOWN; } - OFString DcmSegTypes::segtype2OFString(const DcmSegTypes::E_SegmentationType& value) { - switch(value) - { - case DcmSegTypes::ST_BINARY: return "BINARY"; - case DcmSegTypes::ST_FRACTIONAL: return "FRACTIONAL"; - case DcmSegTypes::ST_UNKNOWN: return "UNKNOWN"; - default: return "Invalid segmentation type (internal error)"; - } + switch (value) + { + case DcmSegTypes::ST_BINARY: + return "BINARY"; + case DcmSegTypes::ST_FRACTIONAL: + return "FRACTIONAL"; + case DcmSegTypes::ST_UNKNOWN: + return "UNKNOWN"; + default: + return "Invalid segmentation type (internal error)"; + } } - DcmSegTypes::E_SegmentationFractionalType DcmSegTypes::OFString2FractionalType(const OFString& value) { - if (value == "PROBABILITY") - return DcmSegTypes::SFT_PROBABILITY; - if (value == "OCCUPANCY") - return DcmSegTypes::SFT_OCCUPANCY; - else - return DcmSegTypes::SFT_UNKNOWN; + if (value == "PROBABILITY") + return DcmSegTypes::SFT_PROBABILITY; + if (value == "OCCUPANCY") + return DcmSegTypes::SFT_OCCUPANCY; + else + return DcmSegTypes::SFT_UNKNOWN; } - - OFString DcmSegTypes::algoType2OFString(DcmSegTypes::E_SegmentAlgoType algo) { - switch (algo) - { - case SAT_AUTOMATIC: return "AUTOMATIC"; break; - case SAT_SEMIAUTOMATIC: return "SEMIAUTOMATIC"; break; - case SAT_MANUAL: return "MANUAL"; break; - default: return ""; - } + switch (algo) + { + case SAT_AUTOMATIC: + return "AUTOMATIC"; + break; + case SAT_SEMIAUTOMATIC: + return "SEMIAUTOMATIC"; + break; + case SAT_MANUAL: + return "MANUAL"; + break; + default: + return ""; + } } - DcmSegTypes::E_SegmentAlgoType DcmSegTypes::OFString2AlgoType(const OFString& algoType) { - if (algoType == "AUTOMATIC") - return DcmSegTypes::SAT_AUTOMATIC; - if (algoType == "MANUAL") - return DcmSegTypes::SAT_MANUAL; - if (algoType == "SEMIAUTOMATIC") - return DcmSegTypes::SAT_SEMIAUTOMATIC; - else - return DcmSegTypes::SAT_UNKNOWN; + if (algoType == "AUTOMATIC") + return DcmSegTypes::SAT_AUTOMATIC; + if (algoType == "MANUAL") + return DcmSegTypes::SAT_MANUAL; + if (algoType == "SEMIAUTOMATIC") + return DcmSegTypes::SAT_SEMIAUTOMATIC; + else + return DcmSegTypes::SAT_UNKNOWN; } -SegmentDescriptionMacro::SegmentDescriptionMacro() : - m_SegmentLabel(DCM_SegmentLabel), - m_SegmentDescription(DCM_SegmentDescription), - m_SegmentAlgorithmType(DcmSegTypes::SAT_UNKNOWN), - m_GeneralAnatomyCode("3" /* General Anatomy Optional Macro* */), - m_SegmentedPropertyCategoryCode(), - m_SegmentedPropertyType() +SegmentDescriptionMacro::SegmentDescriptionMacro() + : m_SegmentLabel(DCM_SegmentLabel) + , m_SegmentDescription(DCM_SegmentDescription) + , m_SegmentAlgorithmType(DcmSegTypes::SAT_UNKNOWN) + , m_GeneralAnatomyCode("3" /* General Anatomy Optional Macro* */) + , m_SegmentedPropertyCategoryCode() + , m_SegmentedPropertyType() { } - SegmentDescriptionMacro::~SegmentDescriptionMacro() { } - void SegmentDescriptionMacro::clearData() { - m_SegmentLabel.clear(); - m_SegmentDescription.clear(); - m_SegmentAlgorithmType = DcmSegTypes::SAT_UNKNOWN; - m_GeneralAnatomyCode.clearData(); - m_SegmentedPropertyCategoryCode.clearData(); - m_SegmentedPropertyType.clearData(); + m_SegmentLabel.clear(); + m_SegmentDescription.clear(); + m_SegmentAlgorithmType = DcmSegTypes::SAT_UNKNOWN; + m_GeneralAnatomyCode.clearData(); + m_SegmentedPropertyCategoryCode.clearData(); + m_SegmentedPropertyType.clearData(); } - OFCondition SegmentDescriptionMacro::read(DcmItem& item) { - /* re-initialize object */ - clearData(); + /* re-initialize object */ + clearData(); - DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentLabel, "1", "1", "SegmentDescriptionMacro"); - DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentDescription, "1", "3", "SegmentDescriptionMacro"); - readSegmentAlgorithmType(item); - m_GeneralAnatomyCode.read(item); - DcmIODUtil::readSingleItem(item, DCM_SegmentedPropertyCategoryCodeSequence, m_SegmentedPropertyCategoryCode, "1", "SegmentDescriptionMacro"); - DcmIODUtil::readSingleItem(item, DCM_SegmentedPropertyTypeCodeSequence, m_SegmentedPropertyType, "1", "SegmentDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentLabel, "1", "1", "SegmentDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentDescription, "1", "3", "SegmentDescriptionMacro"); + readSegmentAlgorithmType(item); + m_GeneralAnatomyCode.read(item); + DcmIODUtil::readSingleItem(item, + DCM_SegmentedPropertyCategoryCodeSequence, + m_SegmentedPropertyCategoryCode, + "1", + "SegmentDescriptionMacro"); + DcmIODUtil::readSingleItem( + item, DCM_SegmentedPropertyTypeCodeSequence, m_SegmentedPropertyType, "1", "SegmentDescriptionMacro"); - return EC_Normal; + return EC_Normal; } - OFCondition SegmentDescriptionMacro::write(DcmItem& item) { - OFCondition result = EC_Normal; - - /* copy all elements to dataset */ - DcmIODUtil::copyElementToDataset(result, item, m_SegmentLabel, "1" /* VM */, "1" /* Type */, "SegmentDescriptionMacro"); - DcmIODUtil::copyElementToDataset(result, item, m_SegmentDescription, "1", "3", "SegmentDescriptionMacro"); - if (result.good()) result = writeSegmentAlgorithmType(item); - if (result.good()) - { - if (m_GeneralAnatomyCode.check(OFTrue /* quiet */).good()) + OFCondition result = EC_Normal; + + /* copy all elements to dataset */ + DcmIODUtil::copyElementToDataset( + result, item, m_SegmentLabel, "1" /* VM */, "1" /* Type */, "SegmentDescriptionMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_SegmentDescription, "1", "3", "SegmentDescriptionMacro"); + if (result.good()) + result = writeSegmentAlgorithmType(item); + if (result.good()) { - result = m_GeneralAnatomyCode.write(item); + if (m_GeneralAnatomyCode.check(OFTrue /* quiet */).good()) + { + result = m_GeneralAnatomyCode.write(item); + } } - } - DcmIODUtil::writeSingleItem(result, DCM_SegmentedPropertyCategoryCodeSequence, m_SegmentedPropertyCategoryCode, item, "1", "SegmentDescriptionMacro"); - DcmIODUtil::writeSingleItem(result, DCM_SegmentedPropertyTypeCodeSequence, m_SegmentedPropertyType, item, "1", "SegmentDescriptionMacro"); - return result; + DcmIODUtil::writeSingleItem(result, + DCM_SegmentedPropertyCategoryCodeSequence, + m_SegmentedPropertyCategoryCode, + item, + "1", + "SegmentDescriptionMacro"); + DcmIODUtil::writeSingleItem( + result, DCM_SegmentedPropertyTypeCodeSequence, m_SegmentedPropertyType, item, "1", "SegmentDescriptionMacro"); + return result; } - -OFCondition SegmentDescriptionMacro::getSegmentLabel(OFString& value, - const signed long pos) +OFCondition SegmentDescriptionMacro::getSegmentLabel(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_SegmentLabel, value, pos); + return DcmIODUtil::getStringValueFromElement(m_SegmentLabel, value, pos); } - -OFCondition SegmentDescriptionMacro::getSegmentDescription(OFString& value, - const signed long pos) +OFCondition SegmentDescriptionMacro::getSegmentDescription(OFString& value, const signed long pos) { - return DcmIODUtil::getStringValueFromElement(m_SegmentDescription, value, pos); + return DcmIODUtil::getStringValueFromElement(m_SegmentDescription, value, pos); } - DcmSegTypes::E_SegmentAlgoType SegmentDescriptionMacro::getSegmentAlgorithmType() { - return m_SegmentAlgorithmType; + return m_SegmentAlgorithmType; } - GeneralAnatomyMacro& SegmentDescriptionMacro::getGeneralAnatomyCode() { - return m_GeneralAnatomyCode; + return m_GeneralAnatomyCode; } - CodeSequenceMacro& SegmentDescriptionMacro::getSegmentedPropertyCategoryCode() { - return m_SegmentedPropertyCategoryCode; + return m_SegmentedPropertyCategoryCode; } - CodeSequenceMacro& SegmentDescriptionMacro::getSegmentedPropertyTypeCode() { - return m_SegmentedPropertyType.m_SegmentedPropertyTypeCode; + return m_SegmentedPropertyType.m_SegmentedPropertyTypeCode; } - -OFVector< CodeSequenceMacro* >& SegmentDescriptionMacro::getSegmentedPropertyTypeModifier() +OFVector& SegmentDescriptionMacro::getSegmentedPropertyTypeModifier() { - return m_SegmentedPropertyType.m_SegmentedPropertyTypeModifierCode; + return m_SegmentedPropertyType.m_SegmentedPropertyTypeModifierCode; } - -OFCondition SegmentDescriptionMacro::setSegmentLabel(const OFString& value, - const OFBool checkValue) +OFCondition SegmentDescriptionMacro::setSegmentLabel(const OFString& value, const OFBool checkValue) { - OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; - if (result.good()) - result = m_SegmentLabel.putOFStringArray(value); - return result; + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_SegmentLabel.putOFStringArray(value); + return result; } - -OFCondition SegmentDescriptionMacro::setSegmentDescription(const OFString& value, - const OFBool checkValue) +OFCondition SegmentDescriptionMacro::setSegmentDescription(const OFString& value, const OFBool checkValue) { - (void)checkValue; - return m_SegmentDescription.putOFStringArray(value); + (void)checkValue; + return m_SegmentDescription.putOFStringArray(value); } - OFCondition SegmentDescriptionMacro::setSegmentAlgorithmType(const DcmSegTypes::E_SegmentAlgoType value) { - m_SegmentAlgorithmType = value; - return EC_Normal; + m_SegmentAlgorithmType = value; + return EC_Normal; } - OFCondition SegmentDescriptionMacro::readSegmentAlgorithmType(DcmItem& item) { - DcmCodeString element(DCM_SegmentAlgorithmType); - OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(item, element, "1", "1", "SegmentDescriptionMacro"); - OFString str; - if (result.good()) - { - element.getOFStringArray(str); - m_SegmentAlgorithmType = DcmSegTypes::OFString2AlgoType(str); - } - - if (m_SegmentAlgorithmType == DcmSegTypes::SAT_UNKNOWN) - { - DCMSEG_ERROR("Invalid value for attribute Segmentation Algorithm Type: " << str); - return SG_EC_InvalidValue; - } - else - return EC_Normal; -} + DcmCodeString element(DCM_SegmentAlgorithmType); + OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(item, element, "1", "1", "SegmentDescriptionMacro"); + OFString str; + if (result.good()) + { + element.getOFStringArray(str); + m_SegmentAlgorithmType = DcmSegTypes::OFString2AlgoType(str); + } + if (m_SegmentAlgorithmType == DcmSegTypes::SAT_UNKNOWN) + { + DCMSEG_ERROR("Invalid value for attribute Segmentation Algorithm Type: " << str); + return SG_EC_InvalidValue; + } + else + return EC_Normal; +} OFCondition SegmentDescriptionMacro::writeSegmentAlgorithmType(DcmItem& item) { - if (m_SegmentAlgorithmType == DcmSegTypes::SAT_UNKNOWN) - { - DCMSEG_ERROR("Segment Algorithm Type not set"); - return SG_EC_InvalidValue; - } - - OFString str = DcmSegTypes::algoType2OFString(m_SegmentAlgorithmType); - return item.putAndInsertOFStringArray(DCM_SegmentAlgorithmType, str); -} + if (m_SegmentAlgorithmType == DcmSegTypes::SAT_UNKNOWN) + { + DCMSEG_ERROR("Segment Algorithm Type not set"); + return SG_EC_InvalidValue; + } + OFString str = DcmSegTypes::algoType2OFString(m_SegmentAlgorithmType); + return item.putAndInsertOFStringArray(DCM_SegmentAlgorithmType, str); +} -SegmentedPropertyTypeCodeItem::SegmentedPropertyTypeCodeItem() : - m_SegmentedPropertyTypeCode(), - m_SegmentedPropertyTypeModifierCode() +SegmentedPropertyTypeCodeItem::SegmentedPropertyTypeCodeItem() + : m_SegmentedPropertyTypeCode() + , m_SegmentedPropertyTypeModifierCode() { - } - SegmentedPropertyTypeCodeItem::~SegmentedPropertyTypeCodeItem() { - DcmIODUtil::freeContainer(m_SegmentedPropertyTypeModifierCode); + DcmIODUtil::freeContainer(m_SegmentedPropertyTypeModifierCode); } - OFCondition SegmentedPropertyTypeCodeItem::check(const OFBool quiet) { - OFCondition result = m_SegmentedPropertyTypeCode.check(quiet); - if (result.good()) - { - result = checkModifiers(quiet); - } - return result; + OFCondition result = m_SegmentedPropertyTypeCode.check(quiet); + if (result.good()) + { + result = checkModifiers(quiet); + } + return result; } - OFCondition SegmentedPropertyTypeCodeItem::checkModifiers(const OFBool quiet) { - OFCondition result; - OFVector::iterator it = m_SegmentedPropertyTypeModifierCode.begin(); - while (it != m_SegmentedPropertyTypeModifierCode.end()) - { - result = (*it)->check(quiet); - if (result.bad()) - return result; - it++; - } - return EC_Normal; + OFCondition result; + OFVector::iterator it = m_SegmentedPropertyTypeModifierCode.begin(); + while (it != m_SegmentedPropertyTypeModifierCode.end()) + { + result = (*it)->check(quiet); + if (result.bad()) + return result; + it++; + } + return EC_Normal; } - void SegmentedPropertyTypeCodeItem::clearData() { - DcmIODUtil::freeContainer(m_SegmentedPropertyTypeModifierCode); - m_SegmentedPropertyTypeCode.clearData(); + DcmIODUtil::freeContainer(m_SegmentedPropertyTypeModifierCode); + m_SegmentedPropertyTypeCode.clearData(); } - -OFCondition SegmentedPropertyTypeCodeItem::read(DcmItem& item, - const OFBool clearOldData) +OFCondition SegmentedPropertyTypeCodeItem::read(DcmItem& item, const OFBool clearOldData) { - OFCondition result; - if (clearOldData) - clearData(); - - m_SegmentedPropertyTypeCode.read(item); - DcmIODUtil::readSubSequence - ( - item, - DCM_SegmentedPropertyTypeModifierCodeSequence, - m_SegmentedPropertyTypeModifierCode, - "1-n", - "3", - "SegmentDescriptionMacro" - ); - return result; + OFCondition result; + if (clearOldData) + clearData(); + + m_SegmentedPropertyTypeCode.read(item); + DcmIODUtil::readSubSequence(item, + DCM_SegmentedPropertyTypeModifierCodeSequence, + m_SegmentedPropertyTypeModifierCode, + "1-n", + "3", + "SegmentDescriptionMacro"); + return result; } - - OFCondition SegmentedPropertyTypeCodeItem::write(DcmItem& item) { - OFCondition result = m_SegmentedPropertyTypeCode.write(item); - if (result.good()) - { - result = checkModifiers(); + OFCondition result = m_SegmentedPropertyTypeCode.write(item); if (result.good()) { - DcmIODUtil::writeSubSequence > - ( - result, - DCM_SegmentedPropertyTypeModifierCodeSequence, - m_SegmentedPropertyTypeModifierCode, - item, - "1-n", - "3", - "SegmentDescriptionMacro" - ); + result = checkModifiers(); + if (result.good()) + { + DcmIODUtil::writeSubSequence >(result, + DCM_SegmentedPropertyTypeModifierCodeSequence, + m_SegmentedPropertyTypeModifierCode, + item, + "1-n", + "3", + "SegmentDescriptionMacro"); + } } - } - return result; + return result; } diff --git a/dcmseg/libsrc/segutils.cc b/dcmseg/libsrc/segutils.cc index b2b647c4..509cf027 100644 --- a/dcmseg/libsrc/segutils.cc +++ b/dcmseg/libsrc/segutils.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, Open Connections GmbH + * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -20,187 +20,159 @@ */ #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmseg/segutils.h" -#include "dcmtk/dcmseg/segdef.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmseg/segdef.h" +#include "dcmtk/dcmseg/segutils.h" -DcmIODTypes::Frame* DcmSegUtils::packBinaryFrame(const Uint8* pixelData, - const Uint16 rows, - const Uint16 columns) +DcmIODTypes::Frame* DcmSegUtils::packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns) { - // Sanity checking - const size_t numPixels = OFstatic_cast(size_t, rows) * columns; - if (numPixels == 0) - { - DCMSEG_ERROR("Unable to pack binary segmentation frame: Rows or Columns is 0"); - return NULL; - } - if (!pixelData) - { - DCMSEG_ERROR("Unable to pack binary segmentation frame: No pixel data provided"); - return NULL; - } - DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); - if (frame == NULL) - { - DCMSEG_ERROR("Could not pack binary segmentation frame: Memory exhausted"); - return NULL; - } - frame->length = getBytesForBinaryFrame(numPixels); - frame->pixData = new Uint8[frame->length]; - if (frame->pixData == 0) - { - delete frame; - return NULL; - } - memset(frame->pixData, 0, frame->length); + // Sanity checking + const size_t numPixels = OFstatic_cast(size_t, rows) * columns; + if (numPixels == 0) + { + DCMSEG_ERROR("Unable to pack binary segmentation frame: Rows or Columns is 0"); + return NULL; + } + if (!pixelData) + { + DCMSEG_ERROR("Unable to pack binary segmentation frame: No pixel data provided"); + return NULL; + } + DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); + if (frame == NULL) + { + DCMSEG_ERROR("Could not pack binary segmentation frame: Memory exhausted"); + return NULL; + } + frame->length = getBytesForBinaryFrame(numPixels); + frame->pixData = new Uint8[frame->length]; + if (frame->pixData == 0) + { + delete frame; + return NULL; + } + memset(frame->pixData, 0, frame->length); - size_t bytePos = 0; - for (size_t count = 0; count < numPixels; count++) - { - // Compute byte position - bytePos = count / 8; - frame->pixData[bytePos] |= (pixelData[count] != 0) /* value to set */ << (count % 8 /* bit position (0-7) within byte */); - } - return frame; + size_t bytePos = 0; + for (size_t count = 0; count < numPixels; count++) + { + // Compute byte position + bytePos = count / 8; + frame->pixData[bytePos] + |= (pixelData[count] != 0) /* value to set */ << (count % 8 /* bit position (0-7) within byte */); + } + return frame; } - -DcmIODTypes::Frame* DcmSegUtils::unpackBinaryFrame(const DcmIODTypes::Frame* frame, - Uint16 rows, - Uint16 cols) +DcmIODTypes::Frame* DcmSegUtils::unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols) { - // Sanity checking - if ( (frame == NULL) || (rows == 0) || (cols == 0) ) - { - DCMSEG_ERROR("Cannot unpack binary frame, invalid input data"); - return NULL; - } - - // Create result frame in memory - size_t numBits = OFstatic_cast(size_t, rows) * cols; - DcmIODTypes::Frame* result = new DcmIODTypes::Frame(); - if (result) - { - result->pixData = new Uint8[numBits]; - if (!result->pixData) + // Sanity checking + if ((frame == NULL) || (rows == 0) || (cols == 0)) { - delete result; + DCMSEG_ERROR("Cannot unpack binary frame, invalid input data"); return NULL; } - result->length = numBits; - } - if ( !result || !(result->pixData) ) - { - DCMSEG_ERROR("Cannot unpack binary frame, memory exhausted"); - return NULL; - } - memset(result->pixData, 0, result->length); - // Transform and copy from packed frame to unpacked result frame - size_t bytePos = 0; - for (size_t count = 0; count < numBits; count++) - { - // Compute byte position - bytePos = count / 8; - // Bit position (0-7) within byte - Uint8 bitpos = (count % 8); - if ( (frame->pixData[bytePos] & (1 << bitpos) /* check whether bit at bitpos is set*/) ) + // Create result frame in memory + size_t numBits = OFstatic_cast(size_t, rows) * cols; + DcmIODTypes::Frame* result = new DcmIODTypes::Frame(); + if (result) { - result->pixData[count] = 1; + result->pixData = new Uint8[numBits]; + if (!result->pixData) + { + delete result; + return NULL; + } + result->length = numBits; } - else + if (!result || !(result->pixData)) { - result->pixData[count] = 0; + DCMSEG_ERROR("Cannot unpack binary frame, memory exhausted"); + return NULL; } - } - return result; -} + memset(result->pixData, 0, result->length); + // Transform and copy from packed frame to unpacked result frame + size_t bytePos = 0; + for (size_t count = 0; count < numBits; count++) + { + // Compute byte position + bytePos = count / 8; + // Bit position (0-7) within byte + Uint8 bitpos = (count % 8); + if ((frame->pixData[bytePos] & (1 << bitpos) /* check whether bit at bitpos is set*/)) + { + result->pixData[count] = 1; + } + else + { + result->pixData[count] = 0; + } + } + return result; +} size_t DcmSegUtils::getBytesForBinaryFrame(const size_t& numPixels) { - // check whether the 1-bit pixels exactly fit into bytes - size_t remainder = numPixels % 8; - // number of bytes that work on an exact fit - size_t bytesRequired = numPixels / 8; - // add one byte if we have a remainder - if (remainder > 0) bytesRequired++; - return bytesRequired; + // check whether the 1-bit pixels exactly fit into bytes + size_t remainder = numPixels % 8; + // number of bytes that work on an exact fit + size_t bytesRequired = numPixels / 8; + // add one byte if we have a remainder + if (remainder > 0) + bytesRequired++; + return bytesRequired; } - -void DcmSegUtils::alignFrameOnBitPosition(Uint8* buf, - size_t bufLen, - Uint8 numBits) +void DcmSegUtils::alignFrameOnBitPosition(Uint8* buf, const size_t bufLen, const Uint8 numBits) { - if (numBits > 7) - { - DCMSEG_ERROR("Invalid input data: shiftFrameBitsLeft() can only shift 0-7 bits"); - return; - } - Uint8 carryOver = 0; - for (size_t x = 0; x < bufLen; x++) - { - // Store current byte since we need to restore its first bits later - Uint8 current = buf[x]; - // Shift pixels given num bits to the left, creating (8 - num bits) - // empty bits at the right - buf[x] <<= numBits; - // If there is a carry over from the previous byte, add it in again (will always be at the end, - // see carry over calculation in next step) - buf[x] |= carryOver; - // Compute carry over bits for next byte to be handled, i.e. those bits at the left that will be - // overwritten in the next byte - carryOver = current >> (8-numBits); - } + if (numBits > 7) + { + DCMSEG_ERROR("Invalid input data: shiftFrameBitsLeft() can only shift 0-7 bits"); + return; + } + Uint8 carryOver = 0; + for (size_t x = 0; x < bufLen; x++) + { + // Store current byte since we need to restore its first bits later + Uint8 current = buf[x]; + // Shift pixels given num bits to the left, creating (8 - num bits) + // empty bits at the right + buf[x] <<= numBits; + // If there is a carry over from the previous byte, add it in again (will always be at the end, + // see carry over calculation in next step) + buf[x] |= carryOver; + // Compute carry over bits for next byte to be handled, i.e. those bits at the left that will be + // overwritten in the next byte + carryOver = current >> (8 - numBits); + } } - -void DcmSegUtils::alignFrameOnByteBoundary(Uint8* buf, - size_t bufLen, - Uint8 numBits) +void DcmSegUtils::alignFrameOnByteBoundary(Uint8* buf, const size_t bufLen, const Uint8 numBits) { - if (numBits > 7) - { - DCMSEG_ERROR("Invalid input data: alignFrameOnByteBoundary() can only shift 0-7 bits"); - return; - } - for (size_t x = 0; x < bufLen-1; x++) - { - // Shift current byte - buf[x] = buf[x] >> numBits; - // isolate portion of next byte that must be shifted into current byte - Uint8 next = (buf[x+1] << (8-numBits)); - // Take over portion from next byte - buf[x] |= next; - } - // Shift last byte manually - buf[bufLen-1] >>= numBits; + return DcmIODUtil::alignFrameOnByteBoundary(buf, bufLen, numBits); } - -void DcmSegUtils::debugDumpBin(Uint8* buffer, - size_t length, - const char* what) +void DcmSegUtils::debugDumpBin(Uint8* buffer, size_t length, const char* what) { - for (size_t n=0; n= 0; i--) - { - result[i]= (b & 1) + '0'; + OFString result("", 8); + for (int i = 7; i >= 0; i--) + { + result[i] = (b & 1) + '0'; - b >>= 1; - } - return result; + b >>= 1; + } + return result; } diff --git a/dcmseg/tests/CMakeLists.txt b/dcmseg/tests/CMakeLists.txt index 75e108df..61b8e20a 100644 --- a/dcmseg/tests/CMakeLists.txt +++ b/dcmseg/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # declare executables -DCMTK_ADD_EXECUTABLE(dcmseg_tests tests tutils) +DCMTK_ADD_EXECUTABLE(dcmseg_tests tests tutils troundtrip.cc tconcat_binary) # make sure executables are linked to the corresponding libraries DCMTK_TARGET_LINK_MODULES(dcmseg_tests dcmseg dcmfg dcmiod dcmdata oflog ofstd) diff --git a/dcmseg/tests/Makefile.dep b/dcmseg/tests/Makefile.dep index b9945927..e10a91ed 100644 --- a/dcmseg/tests/Makefile.dep +++ b/dcmseg/tests/Makefile.dep @@ -1,3 +1,175 @@ +tconcat_binary.o: tconcat_binary.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../include/dcmtk/dcmseg/segdoc.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \ + ../include/dcmtk/dcmseg/segment.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/oftest.h \ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ @@ -47,31 +219,203 @@ tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h -tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \ - ../../ofstd/include/dcmtk/ofstd/oftest.h \ - ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ - ../../ofstd/include/dcmtk/ofstd/oftypes.h \ +troundtrip.o: troundtrip.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmseg/segdoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ ../../ofstd/include/dcmtk/ofstd/ofexport.h \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ - ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ - ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruv.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/oftuple.h \ + ../../ofstd/include/dcmtk/ofstd/ofdiag.h \ + ../../ofstd/include/dcmtk/ofstd/diag/push.def \ + ../../ofstd/include/dcmtk/ofstd/diag/mmtag.def \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuple.h \ + ../../ofstd/include/dcmtk/ofstd/diag/pop.def \ + ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \ + ../../dcmfg/include/dcmtk/dcmfg/fg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofvriant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \ + ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \ + ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \ + ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \ + ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \ + ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \ + ../include/dcmtk/dcmseg/segment.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \ + ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \ + ../../ofstd/include/dcmtk/ofstd/ofstrutl.h \ + ../../ofstd/include/dcmtk/ofstd/oftempf.h +tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ ../../ofstd/include/dcmtk/ofstd/oflimits.h \ ../../config/include/dcmtk/config/arith.h \ ../../ofstd/include/dcmtk/ofstd/oferror.h \ - ../../ofstd/include/dcmtk/ofstd/ofexit.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ ../../oflog/include/dcmtk/oflog/config.h \ @@ -96,36 +440,42 @@ tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmseg/segutils.h ../include/dcmtk/dcmseg/segdef.h \ ../include/dcmtk/dcmseg/segtypes.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ @@ -136,11 +486,9 @@ tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ @@ -170,8 +518,10 @@ tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofexbl.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h diff --git a/dcmseg/tests/Makefile.in b/dcmseg/tests/Makefile.in index 12ce44f3..55b7bfd7 100644 --- a/dcmseg/tests/Makefile.in +++ b/dcmseg/tests/Makefile.in @@ -25,7 +25,7 @@ LOCALLIBS = -ldcmseg -ldcmfg -ldcmiod -ldcmdata -loflog -lofstd $(ZLIBLIBS) \ LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include \ -I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include \ -test_objs = tests.o tutils.o +test_objs = tconcat_binary.o tests.o troundtrip.o tutils.o objs = $(test_objs) progs = tests @@ -37,10 +37,10 @@ tests: $(test_objs) check: tests - ./tests + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests check-exhaustive: tests - ./tests -x + DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests -x install: all diff --git a/dcmseg/tests/tconcat_binary.cc b/dcmseg/tests/tconcat_binary.cc new file mode 100644 index 00000000..5d9224be --- /dev/null +++ b/dcmseg/tests/tconcat_binary.cc @@ -0,0 +1,121 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmseg + * + * Author: Michael Onken + * + * Purpose: Test for creating, writing and reading binary Segmentation objects + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmfg/concatenationcreator.h" +#include "dcmtk/dcmfg/concatenationloader.h" +#include "dcmtk/dcmseg/segdoc.h" +#include "dcmtk/dcmseg/segment.h" +#include "dcmtk/ofstd/oftest.h" + +const OFString ATLAS_FILE = "/home/michael/data/dcm/seg_atlas.dcm"; +const size_t NUM_FRAMES_PER_CONCAT = 24; + +OFTEST(dcmseg_concat_binary) +{ + if (!OFStandard::fileExists(ATLAS_FILE)) + { + DCMSEG_DEBUG("Will not run dcmseg_concat_binary test, input file " << ATLAS_FILE << " missing"); + return; + } + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK(dcmDataDict.isDictionaryLoaded()); + return; + } + + // Loading + DcmSegmentation* seg = NULL; + OFCondition result = DcmSegmentation::loadFile(ATLAS_FILE, seg); + if (result.good()) + { + ConcatenationCreator cc; + result = cc.setCfgFramesPerInstance(NUM_FRAMES_PER_CONCAT); + if (result.good()) + { + seg->setCheckFGOnWrite(OFFalse); + result = seg->writeConcatenation(cc); + if (result.good()) + { + size_t n = 0; + do + { + OFStringStream ss; + ss << "/tmp/concat_" << n; + result = cc.writeNextInstance(ss.str().c_str()); + n++; + } while (result.good()); + if (result != FG_EC_ConcatenationComplete) + { + DCMSEG_ERROR("Could not write concatentation instance: " << result.text()); + OFCHECK(result.good()); + } + } + else + { + DCMSEG_ERROR("Could not write concatentation: " << result.text()); + OFCHECK(result.good()); + } + } + else + { + DCMSEG_ERROR("Could not configure concatentation number of frames to " << NUM_FRAMES_PER_CONCAT << ": " + << result.text()); + OFCHECK(result.good()); + } + } + delete seg; + seg = NULL; + + if (result == FG_EC_ConcatenationComplete) + { + ConcatenationLoader cl; + result = cl.scan("/tmp", "concat*", OFFalse); + if (result.good()) + { + if (cl.getInfo().size() == 1) + { + OFVector frames; + DcmFileFormat dcmff; + result = DcmSegmentation::loadConcatenation(cl, cl.getInfo().begin()->first, seg); + if (result.good()) + { + seg->setCheckFGOnWrite(OFFalse); + result = seg->saveFile("/tmp/atlas_copy.dcm", EXS_LittleEndianExplicit); + if (result.bad()) + { + DCMSEG_ERROR("Unable to write re-assembled Concatenation Source instance: " << result.text()); + OFCHECK(result.good()); + } + } + delete seg; + } + else + { + DCMSEG_ERROR("Unable to load concatenation: Expected 1 but found " + << cl.getInfo().size() << " concatenations in directory /tmp"); + OFCHECK(cl.getInfo().size() > 1); + } + } + } +} diff --git a/dcmseg/tests/tests.cc b/dcmseg/tests/tests.cc index 6e7b4626..e9cb54e1 100644 --- a/dcmseg/tests/tests.cc +++ b/dcmseg/tests/tests.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015, OFFIS e.V. + * Copyright (C) 2015-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -20,7 +20,11 @@ */ #include "dcmtk/config/osconfig.h" + #include "dcmtk/ofstd/oftest.h" OFTEST_REGISTER(dcmseg_utils); +OFTEST_REGISTER(dcmseg_roundtrip); +OFTEST_REGISTER(dcmseg_concat_binary); + OFTEST_MAIN("dcmseg") diff --git a/dcmseg/tests/troundtrip.cc b/dcmseg/tests/troundtrip.cc new file mode 100644 index 00000000..472eaf1e --- /dev/null +++ b/dcmseg/tests/troundtrip.cc @@ -0,0 +1,1041 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmseg + * + * Author: Michael Onken + * + * Purpose: Test for creating, writing and reading Segmentation objects + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmseg/segdoc.h" +#include "dcmtk/dcmseg/segment.h" +#include "dcmtk/ofstd/oftest.h" + +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgpixmsr.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgseg.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofstrutl.h" +#include "dcmtk/ofstd/oftempf.h" +#include "dcmtk/ofstd/oftest.h" + +static const Uint8 NUM_ROWS = 10; +static const Uint8 NUM_COLS = 10; +static const Uint8 NUM_FRAMES = 10; +static const Uint8 NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS; + +static OFString EXPECTED_DUMP; + +static void prepareExpectedDump(); +static DcmSegmentation* create(); +static void setGenericValues(DcmSegmentation* seg); +static void addSharedFGs(DcmSegmentation* seg); +static void addFrames(DcmSegmentation* seg); +static void addDimensions(DcmSegmentation* seg); +static OFString write(DcmSegmentation* seg, DcmDataset& ds); +static void writeAndCheckConcatenation(DcmSegmentation* seg, OFList& concats); +static void checkCreatedObject(const OFString& ds_dump); +static void loadAndCheckConcatenation(const OFList& concats); +static void checkConcatenationInstance(size_t numInstance, DcmSegmentation* srcInstance, DcmDataset* concatInstance); + +OFTEST(dcmseg_roundtrip) +{ + // Make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + // Creation + DcmSegmentation* seg = create(); + setGenericValues(seg); + addSharedFGs(seg); + addFrames(seg); + addDimensions(seg); + + // Write to dataset and compare its dump with expected result + DcmFileFormat dcmff; + DcmDataset* ds = dcmff.getDataset(); + prepareExpectedDump(); + OFString dset_dump = write(seg, *ds); + checkCreatedObject(dset_dump); + + // Save to disk, and re-load to test import + OFTempFile tf; + OFString temp_fn = tf.getFilename(); + OFCHECK(!temp_fn.empty()); + OFCHECK(seg->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good()); + + // Read object from dataset into DcmSegmentation object, write again to dataset and + // check whether object after writing is identical to object after writing. + // the same expected result + delete seg; + seg = NULL; + DcmSegmentation::loadFile(temp_fn, seg).good(); + OFCHECK(seg != OFnullptr); + if (seg) + { + dset_dump = write(seg, *ds); + checkCreatedObject(dset_dump); + } + + // Check writing the object to a concatenation + OFList concats; + writeAndCheckConcatenation(seg, concats); + + // Re-load object from concatenation + loadAndCheckConcatenation(concats); + + OFListIterator(OFFilename) delFile = concats.begin(); + while (delFile != concats.end()) + { + OFStandard::deleteFile(*delFile); + delFile++; + } + delete seg; +} + +static DcmSegmentation* create() +{ + IODGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1"); + ContentIdentificationMacro ci("1", "LABEL", "DESCRIPTION", "Doe^John"); + DcmSegmentation* seg = NULL; + OFCondition result; + DcmSegmentation::createFractionalSegmentation(seg, NUM_ROWS, NUM_COLS, DcmSegTypes::SFT_OCCUPANCY, 255, eq, ci); + OFCHECK(result.good()); + OFCHECK(seg != OFnullptr); + return seg; +} + +static void setGenericValues(DcmSegmentation* seg) +{ + if (!seg) + return; + OFCHECK(seg->getPatient().setPatientName("Bond^James").good()); + OFCHECK(seg->getPatient().setPatientID("007").good()); + OFCHECK(seg->getPatient().setPatientBirthDate("19771007").good()); + OFCHECK(seg->getStudy().setStudyDate("20190801").good()); + OFCHECK(seg->getStudy().setStudyTime("120000").good()); + OFCHECK(seg->getStudy().setStudyID("1").good()); + OFCHECK(seg->getPatientStudy().setPatientAge("040Y").good()); + OFCHECK(seg->getSeries().setSeriesDescription("Test Description").good()); + OFCHECK(seg->getSeries().setSeriesNumber("1").good()); + OFCHECK(seg->getSeries().setPatientPosition("HFS").good()); + + // Those values are usually computed automatically. UIDS are generated and date/times are set to current values. + // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually, + // so that they are not overwritten with new, automatically created values later. + OFCHECK(seg->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good()); + OFCHECK(seg->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good()); + OFCHECK(seg->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good()); + OFCHECK(seg->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good()); + OFCHECK(seg->getGeneralImage().setContentDate("20190927").good()); + OFCHECK(seg->getGeneralImage().setContentTime("153857").good()); +} + +static void addSharedFGs(DcmSegmentation* seg) +{ + if (!seg) + return; + + FGPixelMeasures meas; + OFCHECK(meas.setPixelSpacing("0.1\\0.1").good()); + OFCHECK(meas.setSliceThickness("1.0").good()); + OFCHECK(meas.setSpacingBetweenSlices("0.05").good()); + + FGPlanePosPatient planpo; + OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good()); + + FGPlaneOrientationPatient planor; + OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good()); + + OFCHECK(seg->addForAllFrames(meas).good()); + OFCHECK(seg->addForAllFrames(planpo).good()); + OFCHECK(seg->addForAllFrames(planor).good()); +} + +static void addFrames(DcmSegmentation* seg) +{ + if (!seg) + return; + + FGSegmentation* fg_seg = new FGSegmentation(); + FGFrameContent* fg = new FGFrameContent(); + OFCHECK(fg && fg_seg); + fg->setStackID("1"); + if (fg) + { + for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++) + { + DcmSegment* segment = NULL; + CodeSequenceMacro category("85756007", "SCT", "Tissue"); + CodeSequenceMacro propType("51114001", "SCT", "Artery"); + OFCHECK(DcmSegment::create(segment, "SEGLABEL", category, propType, DcmSegTypes::SAT_AUTOMATIC, "OC_DUMMY") + .good()); + OFCHECK(segment != OFnullptr); + OFCHECK(seg->addSegment(segment, frameNo).good()); + + OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good()); + OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good()); + OFCHECK(fg->setFrameAcquisitionDuration(0.001).good()); + OFCHECK(fg->setInStackPositionNumber(frameNo).good()); + OFCHECK(fg->setDimensionIndexValues(1, 0).good()); + OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good()); + OFVector groups; + groups.push_back(fg); + + Uint8* data = new Uint8[NUM_PIXELS_PER_FRAME]; + for (Uint8 i = 0; i < NUM_PIXELS_PER_FRAME; ++i) + { + data[i] = i; + } + OFCHECK(fg_seg->setReferencedSegmentNumber(frameNo).good()); + OFVector perFrameFGs; + perFrameFGs.push_back(fg); + perFrameFGs.push_back(fg_seg); + OFCHECK(seg->addFrame(data, frameNo, perFrameFGs).good()); + delete[] data; + } + } + delete fg; + delete fg_seg; +} + +static void addDimensions(DcmSegmentation* seg) +{ + if (!seg) + return; + IODMultiframeDimensionModule& dims = seg->getDimensions(); + OFCHECK(dims.addDimensionIndex( + DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM") + .good()); + OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber, + "2.25.30855560781715986879861690673941231222", + DCM_FrameContentSequence, + "STACK_DIM") + .good()); + OFunique_ptr org( + new IODMultiframeDimensionModule::DimensionOrganizationItem); + if (org) + { + org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222"); + dims.getDimensionOrganizationSequence().push_back(org.release()); + } +} + +static OFString write(DcmSegmentation* seg, DcmDataset& ds) +{ + OFCondition result = seg->writeDataset(ds); + OFCHECK(result.good()); + // Make dump and return it + OFStringStream sstream; + ds.print(sstream); + OFSTRINGSTREAM_GETOFSTRING(sstream, dump); + + return dump; +} + +static void writeAndCheckConcatenation(DcmSegmentation* seg, OFList& concats) +{ + ConcatenationCreator cc; + cc.setCfgFramesPerInstance(1); + OFCHECK(seg->writeConcatenation(cc).good()); + size_t numInstances = cc.getNumInstances(); + OFCHECK(numInstances == NUM_FRAMES); + OFCondition result; + for (size_t n = 0; n < numInstances; n++) + { + OFStringStream s; + s << "concat_" << n << "_"; + OFTempFile tf(O_RDWR, "", s.str().c_str(), ".dcm"); + result = cc.writeNextInstance(tf.getFilename()); + OFCHECK(result.good()); + if (result.good()) + { + DcmFileFormat concat; + result = concat.loadFile(tf.getFilename()); + OFCHECK(result.good()); + checkConcatenationInstance(n, seg, concat.getDataset()); + concats.push_back(tf.getFilename()); + tf.stealFile(); + } + } +} + +static void checkConcatenationInstance(size_t numInstance, DcmSegmentation* srcInstance, DcmDataset* concatInstance) +{ + DcmSegmentation* concat = NULL; + OFCHECK(DcmSegmentation::loadDataset(*concatInstance, concat).good()); + size_t numFrames; + numFrames = concat->getNumberOfFrames(); + OFCHECK(numFrames == 1); + size_t numSegs = concat->getNumberOfSegments(); + OFCHECK(numSegs == NUM_FRAMES); + IODMultiFrameFGModule::ConcatenationInfo& ci = concat->getConcatenationInfo(); + OFString val; + OFCHECK(ci.getConcatenationUID(val).good()); + OFCHECK(DcmUniqueIdentifier::checkStringValue(val, "1").good()); + Uint32 frameOffsetNo = 0; + OFCHECK(ci.getConcatenationFrameOffsetNumber(frameOffsetNo).good()); + OFCHECK(frameOffsetNo == numInstance); + Uint16 inConcatNo = 0; + OFCHECK(ci.getInConcatenationNumber(inConcatNo).good()); + OFCHECK(inConcatNo == numInstance + 1); + Uint16 concatTotalNo = 0; + OFCHECK(ci.getInConcatenationTotalNumber(concatTotalNo).good()); + OFCHECK(concatTotalNo == NUM_FRAMES); + + OFString srcUID; + OFCHECK(ci.getSOPInstanceUIDOfConcatenationSource(srcUID).good()); + OFCHECK(srcInstance->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID == val); + + OFCHECK(concat->getSOPCommon().getSOPInstanceUID(val).good()); + OFCHECK(srcUID != val); + + FunctionalGroups::const_iterator srcShared = srcInstance->getFunctionalGroups().getShared()->begin(); + FunctionalGroups::const_iterator cShared = concat->getFunctionalGroups().getShared()->begin(); + size_t numShared = 0; + do + { + OFCHECK(srcShared->second->compare(*cShared->second) == 0); + srcShared++; + cShared++; + numShared++; + } while ((srcShared != srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared != concat->getFunctionalGroups().getShared()->end())); + OFCHECK((srcShared == srcInstance->getFunctionalGroups().getShared()->end()) + && (cShared == concat->getFunctionalGroups().getShared()->end())); + DcmSequenceOfItems* cPerFrame = NULL; + OFCHECK(concatInstance->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, cPerFrame).good()); + OFCHECK(cPerFrame->card() == 1); + + OFBool perFrame = OFFalse; + FGBase* fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_FRAMECONTENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFTrue); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_SEGMENTATION, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFTrue); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PIXELMEASURES, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEPOSPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + fg = NULL; + fg = concat->getFunctionalGroups().get(0, DcmFGTypes::EFG_PLANEORIENTPATIENT, perFrame); + OFCHECK(fg != NULL); + OFCHECK(perFrame == OFFalse); + + const DcmIODTypes::Frame* frame = concat->getFrame(0); + OFCHECK(frame != OFnullptr); + OFCHECK(frame->pixData != OFnullptr); + OFCHECK(OFstatic_cast(Uint8, frame->length) == NUM_PIXELS_PER_FRAME); + for (size_t pix = 0; pix < frame->length; pix++) + { + OFCHECK(frame->pixData[pix] == pix); + } + delete concat; +} + +static void loadAndCheckConcatenation(const OFList& concats) +{ + ConcatenationLoader cl; + OFCondition result = cl.scan(concats); + OFCHECK(result.good()); + if (result.good()) + { + ConcatenationLoader::TScanResult results = cl.getInfo(); + OFCHECK(results.size() == 1); + if (results.size() != 1) + return; + DcmSegmentation* seg = NULL; + result = DcmSegmentation::loadConcatenation(cl, results.begin()->first, seg); + + OFCHECK(result.good()); + if (result.good()) + { + OFStringStream s; + DcmDataset dset; + OFString sop; + result = seg->writeDataset(dset); + + // Patch date and time so that it fits the prepared dump + OFCHECK(dset.putAndInsertOFStringArray(DCM_ContentDate, "20190927").good()); + OFCHECK(dset.putAndInsertOFStringArray(DCM_ContentTime, "153857").good()); + + dset.print(s); + OFCHECK(result.good()); + if (result.good()) + { + checkCreatedObject(s.str().c_str()); + } + delete seg; + } + } +} + +static void prepareExpectedDump() +{ + EXPECTED_DUMP = "\n"; + EXPECTED_DUMP += "# Dicom-Data-Set\n"; + EXPECTED_DUMP += "# Used TransferSyntax: Little Endian Explicit\n"; + EXPECTED_DUMP += "(0008,0008) CS [DERIVED\\PRIMARY] # 16, 2 ImageType\n"; + EXPECTED_DUMP += "(0008,0016) UI =SegmentationStorage # 28, 1 SOPClassUID\n"; + EXPECTED_DUMP + += "(0008,0018) UI [1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813] # 56, 1 SOPInstanceUID\n"; + EXPECTED_DUMP += "(0008,0020) DA [20190801] # 8, 1 StudyDate\n"; + EXPECTED_DUMP += "(0008,0023) DA [20190927] # 8, 1 ContentDate\n"; + EXPECTED_DUMP += "(0008,0030) TM [120000] # 6, 1 StudyTime\n"; + EXPECTED_DUMP += "(0008,0033) TM [153857] # 6, 1 ContentTime\n"; + EXPECTED_DUMP += "(0008,0050) SH (no value available) # 0, 0 AccessionNumber\n"; + EXPECTED_DUMP += "(0008,0060) CS [SEG] # 4, 1 Modality\n"; + EXPECTED_DUMP += "(0008,0070) LO [Open Connections] # 16, 1 Manufacturer\n"; + EXPECTED_DUMP += "(0008,0090) PN (no value available) # 0, 0 ReferringPhysicianName\n"; + EXPECTED_DUMP += "(0008,103e) LO [Test Description] # 16, 1 SeriesDescription\n"; + EXPECTED_DUMP += "(0008,1090) LO [OC CT] # 6, 1 ManufacturerModelName\n"; + EXPECTED_DUMP += "(0010,0010) PN [Bond^James] # 10, 1 PatientName\n"; + EXPECTED_DUMP += "(0010,0020) LO [007] # 4, 1 PatientID\n"; + EXPECTED_DUMP += "(0010,0030) DA [19771007] # 8, 1 PatientBirthDate\n"; + EXPECTED_DUMP += "(0010,0040) CS (no value available) # 0, 0 PatientSex\n"; + EXPECTED_DUMP += "(0010,1010) AS [040Y] # 4, 1 PatientAge\n"; + EXPECTED_DUMP += "(0018,1000) LO [4711] # 4, 1 DeviceSerialNumber\n"; + EXPECTED_DUMP += "(0018,1020) LO [0.1] # 4, 1 SoftwareVersions\n"; + EXPECTED_DUMP += "(0018,5100) CS [HFS] # 4, 1 PatientPosition\n"; + EXPECTED_DUMP + += "(0020,000d) UI [1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811] # 56, 1 StudyInstanceUID\n"; + EXPECTED_DUMP + += "(0020,000e) UI [1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812] # 56, 1 SeriesInstanceUID\n"; + EXPECTED_DUMP += "(0020,0010) SH [1] # 2, 1 StudyID\n"; + EXPECTED_DUMP += "(0020,0011) IS [1] # 2, 1 SeriesNumber\n"; + EXPECTED_DUMP += "(0020,0013) IS [1] # 2, 1 InstanceNumber\n"; + EXPECTED_DUMP += "(0020,0052) UI [2.25.30853397773651184949181049330553108086] # 44, 1 FrameOfReferenceUID\n"; + EXPECTED_DUMP += "(0020,1040) LO (no value available) # 0, 0 PositionReferenceIndicator\n"; + EXPECTED_DUMP += "(0020,9221) SQ (Sequence with explicit length #=1) # 0, 1 DimensionOrganizationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0020,9222) SQ (Sequence with explicit length #=2) # 0, 1 DimensionIndexSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9056) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=4) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,9164) UI [2.25.30855560781715986879861690673941231222] # 44, 1 DimensionOrganizationUID\n"; + EXPECTED_DUMP += " (0020,9165) AT (0020,9057) # 4, 1 DimensionIndexPointer\n"; + EXPECTED_DUMP += " (0020,9167) AT (0020,9111) # 4, 1 FunctionalGroupPointer\n"; + EXPECTED_DUMP += " (0020,9421) LO [STACK_DIM] # 10, 1 DimensionDescriptionLabel\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0028,0002) US 1 # 2, 1 SamplesPerPixel\n"; + EXPECTED_DUMP += "(0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation\n"; + EXPECTED_DUMP += "(0028,0008) IS [10] # 2, 1 NumberOfFrames\n"; + EXPECTED_DUMP += "(0028,0010) US 10 # 2, 1 Rows\n"; + EXPECTED_DUMP += "(0028,0011) US 10 # 2, 1 Columns\n"; + EXPECTED_DUMP += "(0028,0100) US 8 # 2, 1 BitsAllocated\n"; + EXPECTED_DUMP += "(0028,0101) US 8 # 2, 1 BitsStored\n"; + EXPECTED_DUMP += "(0028,0102) US 7 # 2, 1 HighBit\n"; + EXPECTED_DUMP += "(0028,0103) US 0 # 2, 1 PixelRepresentation\n"; + EXPECTED_DUMP += "(0028,2110) CS [00] # 2, 1 LossyImageCompression\n"; + EXPECTED_DUMP += "(0062,0001) CS [FRACTIONAL] # 10, 1 SegmentationType\n"; + EXPECTED_DUMP += "(0062,0002) SQ (Sequence with explicit length #=10) # 0, 1 SegmentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 1 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 2 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 3 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 4 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 5 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 6 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 7 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 8 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 9 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=6) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0062,0003) SQ (Sequence with explicit length #=1) # 0, 1 " + "SegmentedPropertyCategoryCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [85756007] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Tissue] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0062,0004) US 10 # 2, 1 SegmentNumber\n"; + EXPECTED_DUMP += " (0062,0005) LO [SEGLABEL] # 8, 1 SegmentLabel\n"; + EXPECTED_DUMP += " (0062,0008) CS [AUTOMATIC] # 10, 1 SegmentAlgorithmType\n"; + EXPECTED_DUMP += " (0062,0009) LO [OC_DUMMY] # 8, 1 SegmentAlgorithmName\n"; + EXPECTED_DUMP + += " (0062,000f) SQ (Sequence with explicit length #=1) # 0, 1 SegmentedPropertyTypeCodeSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0008,0100) SH [51114001] # 8, 1 CodeValue\n"; + EXPECTED_DUMP + += " (0008,0102) SH [SCT] # 4, 1 CodingSchemeDesignator\n"; + EXPECTED_DUMP += " (0008,0104) LO [Artery] # 6, 1 CodeMeaning\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += "(0062,000e) US 255 # 2, 1 MaximumFractionalValue\n"; + EXPECTED_DUMP += "(0062,0010) CS [OCCUPANCY] # 10, 1 SegmentationFractionalType\n"; + EXPECTED_DUMP += "(0070,0080) CS [LABEL] # 6, 1 ContentLabel\n"; + EXPECTED_DUMP += "(0070,0081) LO [DESCRIPTION] # 12, 1 ContentDescription\n"; + EXPECTED_DUMP += "(0070,0084) PN [Doe^John] # 8, 1 ContentCreatorName\n"; + EXPECTED_DUMP + += "(5200,9229) SQ (Sequence with explicit length #=1) # 0, 1 SharedFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9113) SQ (Sequence with explicit length #=1) # 0, 1 PlanePositionSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0032) DS [0.0\\0.0\\0.0] # 12, 3 ImagePositionPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0020,9116) SQ (Sequence with explicit length #=1) # 0, 1 PlaneOrientationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0020,0037) DS [1.0\\0.0\\0.0\\0.0\\1.0\\0.0] # 24, 6 ImageOrientationPatient\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (0028,9110) SQ (Sequence with explicit length #=1) # 0, 1 PixelMeasuresSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=3) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0018,0050) DS [1.0] # 4, 1 SliceThickness\n"; + EXPECTED_DUMP += " (0018,0088) DS [0.05] # 4, 1 SpacingBetweenSlices\n"; + EXPECTED_DUMP += " (0028,0030) DS [0.1\\0.1] # 8, 2 PixelSpacing\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += "(5200,9230) SQ (Sequence with explicit length #=10) # 0, 1 PerFrameFunctionalGroupsSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 1 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 1 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\1 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 1 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 2 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 2 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\2 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 2 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 3 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 3 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\3 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 3 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 4 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 4 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\4 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 4 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 5 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 5 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\5 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 5 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 6 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 6 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\6 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 6 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 7 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 7 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\7 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 7 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 8 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 8 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\8 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 8 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 9 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 9 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\9 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 9 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n"; + EXPECTED_DUMP += " (0020,9111) SQ (Sequence with explicit length #=1) # 0, 1 FrameContentSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=7) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0018,9074) DT [20190816092557] # 14, 1 FrameAcquisitionDateTime\n"; + EXPECTED_DUMP + += " (0018,9151) DT [20190816092557] # 14, 1 FrameReferenceDateTime\n"; + EXPECTED_DUMP + += " (0018,9220) FD 0.001 # 8, 1 FrameAcquisitionDuration\n"; + EXPECTED_DUMP += " (0020,9056) SH [1] # 2, 1 StackID\n"; + EXPECTED_DUMP += " (0020,9057) UL 10 # 4, 1 InStackPositionNumber\n"; + EXPECTED_DUMP + += " (0020,9156) US 10 # 2, 1 FrameAcquisitionNumber\n"; + EXPECTED_DUMP += " (0020,9157) UL 1\\10 # 8, 2 DimensionIndexValues\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += " (0062,000a) SQ (Sequence with explicit length #=1) # 0, 1 SegmentIdentificationSequence\n"; + EXPECTED_DUMP += " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n"; + EXPECTED_DUMP + += " (0062,000b) US 10 # 2, 1 ReferencedSegmentNumber\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP += " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n"; + EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + EXPECTED_DUMP + += "(7fe0,0010) OB " + "00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a" + "\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\3" + "5\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\" + "50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06" + "\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\2" + "1\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\" + "3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56" + "\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0" + "d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\" + "28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42" + "\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5" + "d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\" + "14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e" + "\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\4" + "9\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\" + "00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a" + "\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\3" + "5\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\" + "50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06" + "\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\2" + "1\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\" + "3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56" + "\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0" + "d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\" + "28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42" + "\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5" + "d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\" + "14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e" + "\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\4" + "9\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\" + "00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a" + "\\1b\\1c\\1d\\1e\\1f\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\3" + "5\\36\\37\\38\\39\\3a\\3b\\3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\" + "50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63\\00\\01\\02\\03\\04\\05\\06" + "\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\1a\\1b\\1c\\1d\\1e\\1f\\20\\2" + "1\\22\\23\\24\\25\\26\\27\\28\\29\\2a\\2b\\2c\\2d\\2e\\2f\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\3a\\3b\\" + "3c\\3d\\3e\\3f\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\4a\\4b\\4c\\4d\\4e\\4f\\50\\51\\52\\53\\54\\55\\56" + "\\57\\58\\59\\5a\\5b\\5c\\5d\\5e\\5f\\60\\61\\62\\63 # 1000, 1 PixelData\n"; +} + +static void checkCreatedObject(const OFString& ds_dump) +{ + OFBool dump_ok = (ds_dump == EXPECTED_DUMP); + OFCHECK(dump_ok); + if (!dump_ok) + { + CERR << "Dump produced: " << OFendl << ds_dump << OFendl; + CERR << "------------------------------------" << OFendl; + CERR << "Dump expected: " << OFendl << EXPECTED_DUMP << OFendl; + CERR << "------------------------------------" << OFendl; + } +} diff --git a/dcmseg/tests/tutils.cc b/dcmseg/tests/tutils.cc index 4eaf1f86..36298f2c 100644 --- a/dcmseg/tests/tutils.cc +++ b/dcmseg/tests/tutils.cc @@ -19,55 +19,54 @@ * */ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ -#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ - -#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmiod/iodutil.h" #include "dcmtk/dcmseg/segutils.h" - +#include "dcmtk/ofstd/oftest.h" #define bufLen 4 static void resetBuf(Uint8* buf, const size_t length) { - if (length != bufLen) return; - buf[0] = 170; // 10101010 - buf[1] = 204; // 11001100 - buf[2] = 240; // 11110000 - buf[3] = 15; // 00001111 + if (length != bufLen) + return; + buf[0] = 170; // 10101010 + buf[1] = 204; // 11001100 + buf[2] = 240; // 11110000 + buf[3] = 15; // 00001111 } OFTEST(dcmseg_utils) { - // buf, always initialized/reset with: 10101010 11001100 11110000 00001111 - Uint8 buf[bufLen]; - - resetBuf(buf, bufLen); - DcmSegUtils::alignFrameOnBitPosition(buf, 4, 2); - OFCHECK(buf[0] == 168); // 10101000 - OFCHECK(buf[1] == 50); // 00110010 - OFCHECK(buf[2] == 195); // 11000011 - OFCHECK(buf[3] == 63); // 00111111 + // buf, always initialized/reset with: 10101010 11001100 11110000 00001111 + Uint8 buf[bufLen]; - resetBuf(buf, bufLen); - DcmSegUtils::alignFrameOnByteBoundary(buf, 4, 2); - OFCHECK(buf[0] == 42); // 00101010 - OFCHECK(buf[1] == 51); // 00110011 - OFCHECK(buf[2] == 252); // 11111100 - OFCHECK(buf[3] == 3); // 00000011 + resetBuf(buf, bufLen); + DcmSegUtils::alignFrameOnBitPosition(buf, 4, 2); + OFCHECK(buf[0] == 168); // 10101000 + OFCHECK(buf[1] == 50); // 00110010 + OFCHECK(buf[2] == 195); // 11000011 + OFCHECK(buf[3] == 63); // 00111111 - resetBuf(buf, bufLen); - DcmSegUtils::alignFrameOnBitPosition(buf, 4, 7); - OFCHECK(buf[0] == 0); - OFCHECK(buf[1] == 85); // 01010101 - OFCHECK(buf[2] == 102); // 01100110 - OFCHECK(buf[3] == 248); // 11111000 + resetBuf(buf, bufLen); + DcmSegUtils::alignFrameOnByteBoundary(buf, 4, 2); + OFCHECK(buf[0] == 42); // 00101010 + OFCHECK(buf[1] == 51); // 00110011 + OFCHECK(buf[2] == 252); // 11111100 + OFCHECK(buf[3] == 3); // 00000011 - resetBuf(buf, bufLen); - DcmSegUtils::alignFrameOnByteBoundary(buf, 4, 7); - OFCHECK(buf[0] == 153); // 10011001 - OFCHECK(buf[1] == 225); // 11100001 - OFCHECK(buf[2] == 31); // 00011111 - OFCHECK(buf[3] == 0); + resetBuf(buf, bufLen); + DcmSegUtils::alignFrameOnBitPosition(buf, 4, 7); + OFCHECK(buf[0] == 0); + OFCHECK(buf[1] == 85); // 01010101 + OFCHECK(buf[2] == 102); // 01100110 + OFCHECK(buf[3] == 248); // 11111000 + resetBuf(buf, bufLen); + DcmSegUtils::alignFrameOnByteBoundary(buf, 4, 7); + OFCHECK(buf[0] == 153); // 10011001 + OFCHECK(buf[1] == 225); // 11100001 + OFCHECK(buf[2] == 31); // 00011111 + OFCHECK(buf[3] == 0); } diff --git a/dcmsign/apps/Makefile.dep b/dcmsign/apps/Makefile.dep index a836795b..7b05d881 100644 --- a/dcmsign/apps/Makefile.dep +++ b/dcmsign/apps/Makefile.dep @@ -53,13 +53,17 @@ dcmsign.o: dcmsign.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmsign/sipurpos.h ../include/dcmtk/dcmsign/dcsighlp.h \ ../include/dcmtk/dcmsign/sinullpr.h ../include/dcmtk/dcmsign/sisprof.h \ ../include/dcmtk/dcmsign/sibrsapr.h ../include/dcmtk/dcmsign/siautopr.h \ - ../include/dcmtk/dcmsign/sicreapr.h ../include/dcmtk/dcmsign/simac.h \ + ../include/dcmtk/dcmsign/sicreapr.h ../include/dcmtk/dcmsign/sisrpr.h \ + ../include/dcmtk/dcmsign/sisrvpr.h ../include/dcmtk/dcmsign/simac.h \ ../include/dcmtk/dcmsign/simd5.h ../include/dcmtk/dcmsign/sisha1.h \ ../include/dcmtk/dcmsign/sisha256.h ../include/dcmtk/dcmsign/sisha384.h \ ../include/dcmtk/dcmsign/sisha512.h ../include/dcmtk/dcmsign/siripemd.h \ ../include/dcmtk/dcmsign/siprivat.h ../include/dcmtk/dcmsign/sicert.h \ + ../include/dcmtk/dcmsign/sitsfs.h ../include/dcmtk/dcmsign/sitstamp.h \ + ../include/dcmtk/dcmsign/sicertvf.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ diff --git a/dcmsign/apps/dcmsign.cc b/dcmsign/apps/dcmsign.cc index 2097ce8d..ce5317ab 100644 --- a/dcmsign/apps/dcmsign.cc +++ b/dcmsign/apps/dcmsign.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2018, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -41,18 +41,18 @@ static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; -static OFLogger dcmsignLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); - #define APPLICATION_ABSTRACT "Sign and Verify DICOM Files" - #ifdef WITH_OPENSSL #include "dcmtk/dcmsign/dcsignat.h" +#include "dcmtk/dcmsign/dcsighlp.h" #include "dcmtk/dcmsign/sinullpr.h" #include "dcmtk/dcmsign/sibrsapr.h" #include "dcmtk/dcmsign/siautopr.h" #include "dcmtk/dcmsign/sicreapr.h" +#include "dcmtk/dcmsign/sisrpr.h" +#include "dcmtk/dcmsign/sisrvpr.h" #include "dcmtk/dcmsign/simac.h" #include "dcmtk/dcmsign/simd5.h" #include "dcmtk/dcmsign/sisha1.h" @@ -62,13 +62,17 @@ static OFLogger dcmsignLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APP #include "dcmtk/dcmsign/siripemd.h" #include "dcmtk/dcmsign/siprivat.h" #include "dcmtk/dcmsign/sicert.h" +#include "dcmtk/dcmsign/sitsfs.h" +#include "dcmtk/dcmsign/sicertvf.h" +#include "dcmtk/dcmsign/siexit.h" #include "dcmtk/dcmdata/dctk.h" - BEGIN_EXTERN_C #include +#include /* for OPENSSL_NO_EC */ END_EXTERN_C + // ******************************************** enum DcmSignOperation @@ -76,616 +80,11 @@ enum DcmSignOperation DSO_verify, DSO_sign, DSO_signItem, + DSO_insertTimestamp, DSO_remove, DSO_removeAll }; -/* reads an attribute tag in the form "gggg,eeee" and adds it - * to the given attribute tag list - * @param c input string - * @param tagList list to be added to - * @return true if successful, false otherwise - */ -static OFBool addTag(const char *c, DcmAttributeTag& tagList) -{ - OFBool result = OFFalse; - unsigned int group = 0xffff; - unsigned int elem = 0xffff; - if (sscanf(c, "%x,%x", &group, &elem ) != 2 ) - { - /* it is a name */ - const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); - const DcmDictEntry *dicent = globalDataDict.findEntry(c); - if (dicent) - { - if (EC_Normal == tagList.putTagVal(dicent->getKey(), tagList.getVM())) result = OFTrue; - } - dcmDataDict.rdunlock(); - } else { - if (EC_Normal == tagList.putTagVal(DcmTagKey(group,elem), tagList.getVM())) result = OFTrue; - } - return result; -} - -/* scans a token from the given string and returns it. Ignores leading whitespace. - * @param c string to parse - * @param pos position within string, modified after successful scan - * @param key tag key returned in this parameter if return value is "tag key". - * @param idx index returned in this parameter if return value is "index". - * @return -1 for "EOF", 0 for "parse error", 1 for "tag key", 2 for "index", 3 for "period" - */ -static int readNextToken(const char *c, int& pos, DcmTagKey& key, Uint32& idx) -{ - OFString aString; - int lpos = pos; - int spos = 0; - while(isspace(OFstatic_cast(unsigned char, c[lpos]))) ++lpos; // ignore leading space - - if (c[lpos]=='\0') return -1; // EOF - if (c[lpos]=='.') - { - ++pos; - return 3; // period - } - if (c[lpos]=='[') - { - spos = ++lpos; - while ((c[lpos] >= '0')&&(c[lpos] <= '9')) ++lpos; - if (c[lpos] != ']') return 0; // parse error - unsigned long newindex = 0; - if (1 != sscanf(c+spos,"%lu", &newindex)) return 0; // parse error - idx = OFstatic_cast(Uint32, newindex); - pos = ++lpos; - return 2; // index - } - if (c[lpos]=='(') - { - spos = ++lpos; - while ((c[lpos] != ')')&&(c[lpos] != '\0')) ++lpos; - if (c[lpos] != ')') return 0; // parse error - unsigned int group=0; - unsigned int elem=0; - if (2 != sscanf(c+spos,"%x,%x", &group, &elem)) return 0; // parse error - key = DcmTagKey(group,elem); - pos = ++lpos; - return 1; // tag key - } - spos = lpos; - while ( ((c[lpos] >= 'a')&&(c[lpos] <= 'z')) || ((c[lpos] >= 'A')&&(c[lpos] <= 'Z')) || ((c[lpos] >= '0')&&(c[lpos] <= '9'))) ++lpos; - aString.append(c + spos, (lpos-spos)); - const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); - const DcmDictEntry *dicent = globalDataDict.findEntry(aString.c_str()); - if (dicent) - { - key = dicent->getKey(); - dcmDataDict.rdunlock(); - pos = lpos; - return 1; // tag key; - } - dcmDataDict.rdunlock(); - OFLOG_ERROR(dcmsignLogger, "attribute name '" << aString.c_str() << "' unknown."); - return 0; // parse error -} - -/* reads a complete text file (max 64K) into a memory block - * and returns a pointer to the memory block. - * memory must be freed by called. - * @param filename file to be read - * @return pointer to memory block if successful, NULL otherwise. - */ -static char *readTextFile(const char *filename) -{ - char *result = NULL; - FILE *file = fopen(filename, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - long numBytes = ftell(file); - fseek(file, 0, SEEK_SET); - if (numBytes > 65536) - { - OFLOG_WARN(dcmsignLogger, "text file too large, ignoring everything beyond 64K."); - numBytes = 65536; - } - result = new char[numBytes]; - if (result) - { - if (OFstatic_cast(size_t, numBytes) != fread(result, 1, OFstatic_cast(size_t, numBytes), file)) - { - OFLOG_WARN(dcmsignLogger, "read error in file " << filename); - delete[] result; - result = NULL; - } - } - fclose(file); - } else { - OFLOG_ERROR(dcmsignLogger, "file not found: " << filename); - } - return result; -} - -/* reads a list of attributes from a text file. - * The attributes can be in the form (gggg,eeee) or can be dictionary names, - * separated by arbitrary whitespace. - * @param filename file to be read from - * @param tagList attribute tags are added to this list - * @return 0 if successful, a program exit code otherwise - */ -static int parseTextFile(const char *filename, DcmAttributeTag& tagList) -{ - char *c=readTextFile(filename); - if (c==NULL) return 10; // bail out - int position = 0; - int token = 0; - Uint32 idx = 0; - DcmTagKey key; - int result = 0; - do - { - token = readNextToken(c, position, key, idx); - if (token == 1) // we have read a tag key - { - if (EC_Normal != tagList.putTagVal(key, tagList.getVM())) - { - result = 10; - token = -1; - } - } - else if (token >= 0) - { - OFLOG_ERROR(dcmsignLogger, "parse error in text file '" << filename << "'"); - result = 10; - token = -1; - } - } while (token >= 0); - delete[] c; - return result; -} - - -/* locates a specific item within the given dataset. - * @param dataset dataset to be searched - * @param location location string. Format is "sequence[item]{.sequence[item]}*" - * Where sequence can be (gggg,eeee) or a dictionary name and items - * within sequences are counted from zero. - * @return pointer to the item searched if found, NULL otherwise - */ -static DcmItem *locateItemforSignatureCreation(DcmItem& dataset, const char *location) -{ - DcmTagKey key; - Uint32 idx; - int pos = 0; - int token = 0; - int expected = 1; - OFBool finished = OFFalse; - DcmItem *result = &dataset; - DcmSequenceOfItems *sq = NULL; - DcmStack stack; - do - { - token = readNextToken(location, pos, key, idx); - if ((token != expected)&&(token != -1)) - { - OFLOG_ERROR(dcmsignLogger, "parse error in item location string '" << location << "'"); - return NULL; - } - if (token == -1) - { - if (! finished) - { - OFLOG_ERROR(dcmsignLogger, "item location string '" << location << "' incomplete."); - return NULL; - } - return result; - } - if (token == 1) - { - // we have read a tag key - stack.clear(); - if (EC_Normal != result->search(key, stack, ESM_fromHere, OFFalse)) - { - OFLOG_ERROR(dcmsignLogger, "attribute " << key << " not found in dataset (item location string is '" << location << "')"); - return NULL; - } - if (stack.top()->ident() == EVR_SQ) - { - sq = OFstatic_cast(DcmSequenceOfItems *, (stack.top())); - } else { - OFLOG_ERROR(dcmsignLogger, "attribute " << key << " is not a sequence (item location string is '" << location << "')"); - return NULL; - } - expected = 2; - finished = OFFalse; - } - else if (token == 2) - { - // we have read an index - if (sq == NULL) - { - OFLOG_ERROR(dcmsignLogger, "sequence not found in item location string '" << location << "'"); - return NULL; - } - if (idx >= sq->card()) - { - OFLOG_ERROR(dcmsignLogger, "sequence " << sq->getTag() << " only has " << sq->card() - << " items, cannot locate item " << idx << " (item location string is '" << location << "')"); - return NULL; - } - result = sq->getItem(idx); - if (result == NULL) - { - OFLOG_ERROR(dcmsignLogger, "item not found in item location string '" << location << "'"); - return NULL; - } - expected = 3; - finished = OFTrue; - } - else if (token == 3) - { - // we have read a period - expected = 1; - finished = OFFalse; - } - } while (token > 0); - return NULL; -} - -/* performs a signature operation on a given dataset - * @param dataset to sign - * @param key private key for signature - * @param cert certificate for signature - * @param opt_mac MAC for signature - * @param opt_profile security profile for signature - * @param opt_tagList list of attribute tags, may be NULL - * @return 0 if successful, a program exit code otherwise - */ -static int do_sign( - DcmItem *dataset, - SiPrivateKey& key, - SiCertificate& cert, - SiMAC *opt_mac, - SiSecurityProfile *opt_profile, - DcmAttributeTag *opt_tagList, - E_TransferSyntax opt_signatureXfer, - FILE *dumpFile) -{ - OFCondition sicond = EC_Normal; - DcmSignature signer; - signer.attach(dataset); - signer.setDumpFile(dumpFile); - sicond = signer.createSignature(key, cert, *opt_mac, *opt_profile, opt_signatureXfer, opt_tagList); - if (sicond != EC_Normal) - { - OFLOG_ERROR(dcmsignLogger, sicond.text() << ": while creating signature in main dataset"); - return 1; - } - return 0; -} - -/* print the location stack into the given stack. - * It is assumed that the stack top is a DigitalSignatureSequence which is not printed - * and that the stack bottom is the main dataset, which is also not printed. - * @param stack search stack, as returned by DcmSignature::findFirstSignatureItem() etc. - * @param str printable text returned in this string. - */ -static void printSignatureItemPosition(DcmStack& stack, OFString& str) -{ - str.clear(); - DcmObject *elem = NULL; - DcmSequenceOfItems *sq = NULL; - unsigned long sqCard=0; - const char *tagname = NULL; - unsigned long m=0; - char buf[20]; - - if (stack.card() > 2) - { - // signature is located within a sequence - for (unsigned long l=stack.card()-2; l>0; --l) // loop over all elements except the stack top and bottom - { - elem = stack.elem(l); - if (elem) - { - if ((elem->ident() == EVR_item) && sq) - { - sqCard = sq->card(); - for (m=0; mgetItem(m) == elem) - { - sprintf(buf, "[%lu]", m); - str.append(buf); - } - } - } - else - { - if (str.size() > 0) str.append("."); - sq = OFstatic_cast(DcmSequenceOfItems *, elem); - DcmTag currentTag(elem->getTag()); - tagname = currentTag.getTagName(); - if (tagname) str.append(tagname); else - { - sprintf(buf, "(%04x,%04x)", elem->getTag().getGroup(), elem->getTag().getElement()); - str.append(buf); - } - if (elem->ident() == EVR_SQ) sq = OFstatic_cast(DcmSequenceOfItems *, elem); else sq = NULL; - } - } - } - } else { - // signature is located in the main dataset - str = "Main Dataset"; - } -} - -/* performs a signature operation on a sub-item within a dataset - * @param dataset in which to sign - * @param key private key for signature - * @param cert certificate for signature - * @param opt_mac MAC for signature - * @param opt_profile security profile for signature - * @param opt_tagList list of attribute tags, may be NULL - * @param location location string. Format is "sequence[item]{.sequence[item]}*" - * Where sequence can be (gggg,eeee) or a dictionary name and items - * within sequences are counted from zero. - * @return 0 if successful, a program exit code otherwise - */ -static int do_sign_item( - DcmItem *dataset, - SiPrivateKey& key, - SiCertificate& cert, - SiMAC *opt_mac, - SiSecurityProfile *opt_profile, - DcmAttributeTag *opt_tagList, - const char *opt_location, - E_TransferSyntax opt_signatureXfer, - FILE *dumpFile) -{ - OFCondition sicond = EC_Normal; - DcmSignature signer; - DcmItem *sigItem = locateItemforSignatureCreation(*dataset, opt_location); - if (sigItem == NULL) return 1; - - signer.detach(); - signer.attach(sigItem); - signer.setDumpFile(dumpFile); - sicond = signer.createSignature(key, cert, *opt_mac, *opt_profile, opt_signatureXfer, opt_tagList); - if (sicond != EC_Normal) - { - OFLOG_ERROR(dcmsignLogger, sicond.text() << ": while creating signature in item '" << opt_location << "'"); - return 1; - } - signer.detach(); - return 0; -} - -/* verify all signatures in the given dataset and print results to COUT. - * @param dataset dataset to verify - * @return 0 if successful, a program exit code otherwise - */ -static int do_verify( - DcmItem *dataset) -{ - OFCondition sicond = EC_Normal; - DcmStack stack; - DcmSignature signer; - OFString aString; - int counter = 0; - int corrupt_counter = 0; - unsigned long numSignatures = 0; - unsigned long l=0; - Uint16 macID = 0; - DcmAttributeTag at(DCM_DataElementsSigned); - DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); - DcmTagKey tagkey; - DcmTag tag; - const char *tagName = NULL; - - while (sigItem) - { - signer.attach(sigItem); - numSignatures = signer.numberOfSignatures(); - for (l=0; lgetKeyType()==EKT_none)) - OFLOG_INFO(dcmsignLogger, " none"); - else - { - OFLOG_INFO(dcmsignLogger, " X.509v" << cert->getX509Version()); - cert->getCertSubjectName(aString); - OFLOG_INFO(dcmsignLogger, " Subject : " << aString); - - cert->getCertIssuerName(aString); - OFLOG_INFO(dcmsignLogger, " Issued by : " << aString); - OFLOG_INFO(dcmsignLogger, " Serial no. : " << cert->getCertSerialNo()); - cert->getCertValidityNotBefore(aString); - OFLOG_INFO(dcmsignLogger, " Validity : not before " << aString); - cert->getCertValidityNotAfter(aString); - OFLOG_INFO(dcmsignLogger, " Validity : not after " << aString); - switch (cert->getKeyType()) - { - case EKT_RSA: - OFLOG_INFO(dcmsignLogger, " Public key : RSA, " << cert->getCertKeyBits() << " bits"); - break; - case EKT_DSA: - OFLOG_INFO(dcmsignLogger, " Public key : DSA, " << cert->getCertKeyBits() << " bits"); - break; - case EKT_DH: - OFLOG_INFO(dcmsignLogger, " Public key : DH, " << cert->getCertKeyBits() << " bits"); - break; - case EKT_none: // should never happen - OFLOG_INFO(dcmsignLogger, " Public key : none"); - break; - } - } - aString = " Verification : "; - } else { - OFLOG_INFO(dcmsignLogger, " Location : " << aString); - aString = " Verification : "; - } - sicond = signer.verifyCurrent(); - if (sicond.good()) - { - OFLOG_WARN(dcmsignLogger, aString << "OK\n"); - } else { - corrupt_counter++; - OFLOG_WARN(dcmsignLogger, aString << sicond.text() << "\n"); - } - } - } - signer.detach(); - sigItem = DcmSignature::findNextSignatureItem(*dataset, stack); - } - if (counter == 0) - OFLOG_WARN(dcmsignLogger, "no signatures found in dataset."); - else - OFLOG_INFO(dcmsignLogger, counter << " signatures verified in dataset, " << corrupt_counter << " corrupted."); - return 0; -} - -/* remove all signatures from the given dataset, print action details. - * @param dataset dataset to modify - * @return 0 if successful, a program exit code otherwise - */ -static int do_remove_all( - DcmItem *dataset) -{ - OFCondition sicond = EC_Normal; - DcmSignature signer; - int counter = 0; - OFString aString; - DcmStack stack; - DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); - while (sigItem) - { - signer.attach(sigItem); - while (signer.numberOfSignatures() > 0) - { - ++counter; - if (EC_Normal == signer.selectSignature(0)) - { - if (EC_Normal == signer.getCurrentSignatureUID(aString)) - OFLOG_WARN(dcmsignLogger, "Signature #" << counter << " UID=" << aString); - else - OFLOG_WARN(dcmsignLogger, "Signature #" << counter << " UID=(unknown)"); - printSignatureItemPosition(stack, aString); - OFLOG_WARN(dcmsignLogger, " Location : " << aString); - } - sicond = signer.removeSignature(0); - if (sicond != EC_Normal) - { - OFLOG_ERROR(dcmsignLogger, sicond.text() << ": while removing signature"); - return 1; - } - } - signer.detach(); - stack.pop(); // remove pointer to the Digital Signatures Sequence that we've just deleted. - sigItem = DcmSignature::findNextSignatureItem(*dataset, stack); - } - - OFLOG_INFO(dcmsignLogger, counter << " signatures found and removed from dataset."); - return 0; -} - -/* remove the signature with the given UID from the dataset, print action details. - * @param dataset dataset to modify - * @param opt_location Digital Signature UID of the signature to remove - * @return 0 if successful, a program exit code otherwise - */ -static int do_remove( - DcmItem *dataset, - const char *opt_location) -{ - OFCondition sicond = EC_Normal; - DcmSignature signer; - OFString aString; - DcmStack stack; - unsigned long cardSQ; - unsigned long i; - DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); - while (sigItem) - { - signer.attach(sigItem); - cardSQ = signer.numberOfSignatures(); - for (i=0; i 1) cmd.getParam(2, opt_ofname); - OFLog::configureFromCommandLine(cmd, app); cmd.beginOptionBlock(); @@ -832,29 +309,31 @@ int main(int argc, char *argv[]) if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; cmd.endOptionBlock(); - cmd.beginOptionBlock(); - if (cmd.findOption("--read-xfer-auto")) - opt_ixfer = EXS_Unknown; - if (cmd.findOption("--read-xfer-detect")) - dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-auto")) opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) dcmAutoDetectDatasetXfer.set(OFTrue); if (cmd.findOption("--read-xfer-little")) { - app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); - opt_ixfer = EXS_LittleEndianExplicit; + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; } if (cmd.findOption("--read-xfer-big")) { - app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); - opt_ixfer = EXS_BigEndianExplicit; + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; } if (cmd.findOption("--read-xfer-implicit")) { - app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); - opt_ixfer = EXS_LittleEndianImplicit; + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; } cmd.endOptionBlock(); + cmd.beginOptionBlock(); + if (cmd.findOption("--retain-un")) dcmEnableUnknownVRConversion.set(OFFalse); + if (cmd.findOption("--convert-un")) dcmEnableUnknownVRConversion.set(OFTrue); + cmd.endOptionBlock(); + cmd.beginOptionBlock(); if (cmd.findOption("--verify")) { @@ -875,6 +354,18 @@ int main(int argc, char *argv[]) app.checkValue(cmd.getValue(opt_certfile)); app.checkValue(cmd.getValue(opt_location)); } + if (cmd.findOption("--insert-timestamp")) + { + opt_operation = DSO_insertTimestamp; + if (opt_ofname == NULL) app.printError("parameter dcmfile-out required for --insert-timestamp"); + app.checkValue(cmd.getValue(opt_ts_queryfile)); + app.checkValue(cmd.getValue(opt_ts_responsefile)); + app.checkValue(cmd.getValue(opt_ts_uidfile)); + opt_timeStamp = new SiTimeStampFS(); + opt_timeStamp->setTSQFilename(opt_ts_queryfile); + opt_timeStamp->setTSRFilename(opt_ts_responsefile); + opt_timeStamp->setUIDFilename(opt_ts_uidfile); + } if (cmd.findOption("--remove")) { opt_operation = DSO_remove; @@ -887,9 +378,117 @@ int main(int argc, char *argv[]) if (opt_ofname == NULL) app.printError("parameter dcmfile-out required for --remove-all"); } cmd.endOptionBlock(); - if ((opt_operation == DSO_verify) && opt_ofname) app.printError("parameter dcmfile-out not allowed for --verify"); + cmd.beginOptionBlock(); + if (cmd.findOption("--pem-keys")) opt_keyFileFormat = X509_FILETYPE_PEM; + if (cmd.findOption("--der-keys")) opt_keyFileFormat = X509_FILETYPE_ASN1; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--verify-if-present")) + { + app.checkDependence("--verify-if-present", "--verify", (opt_operation == DSO_verify)); + opt_verificationPolicy = ESVP_verifyIfPresent; + } + if (cmd.findOption("--require-sig")) + { + app.checkDependence("--require-sig", "--verify", (opt_operation == DSO_verify)); + opt_verificationPolicy = ESVP_requireSignature; + } + if (cmd.findOption("--require-creator")) + { + app.checkDependence("--require-creator", "--verify", (opt_operation == DSO_verify)); + opt_verificationPolicy = ESVP_requireCreatorRSASignature; + } + if (cmd.findOption("--require-auth")) + { + app.checkDependence("--require-auth", "--verify", (opt_operation == DSO_verify)); + opt_verificationPolicy = ESVP_requireAuthorizationRSASignature; + } + if (cmd.findOption("--require-sr")) + { + app.checkDependence("--require-sr", "--verify", (opt_operation == DSO_verify)); + opt_verificationPolicy = ESVP_requireSRRSASignature; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--verify-ts")) + { + app.checkDependence("--verify-ts", "--verify", (opt_operation == DSO_verify)); + opt_timestampPolicy = ETVP_verifyTSIfPresent; + } + if (cmd.findOption("--ignore-ts")) + { + app.checkDependence("--ignore-ts", "--verify", (opt_operation == DSO_verify)); + opt_timestampPolicy = ETVP_ignoreTS; + } + if (cmd.findOption("--require-ts")) + { + app.checkDependence("--require-ts", "--verify", (opt_operation == DSO_verify)); + opt_timestampPolicy = ETVP_requireTS; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_First)) + { + app.checkDependence("--add-cert-file", "--verify", (opt_operation == DSO_verify)); + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (certVerifier.addTrustedCertificateFile(current, opt_keyFileFormat).bad()) + { + DCMSIGN_WARN("unable to load certificate file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_Next)); + } + if (cmd.findOption("--add-ucert-file", 0, OFCommandLine::FOM_First)) + { + app.checkDependence("--add-ucert-file", "--verify", (opt_operation == DSO_verify)); + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (certVerifier.addUntrustedCertificateFile(current, opt_keyFileFormat).bad()) + { + DCMSIGN_WARN("unable to load certificate file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-ucert-file", 0, OFCommandLine::FOM_Next)); + } + if (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_First)) + { + app.checkDependence("--add-cert-dir", "--verify", (opt_operation == DSO_verify)); + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (certVerifier.addTrustedCertificateDir(current, opt_keyFileFormat).bad()) + { + DCMSIGN_WARN("unable to load certificates from directory '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_Next)); + } + if (cmd.findOption("--add-crl-file", 0, OFCommandLine::FOM_First)) + { + app.checkDependence("--add-crl-file", "--verify", (opt_operation == DSO_verify)); + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (certVerifier.addCertificateRevocationList(current, opt_keyFileFormat).bad()) + { + DCMSIGN_WARN("unable to load CRL file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-crl-file", 0, OFCommandLine::FOM_Next)); + } + if (cmd.findOption("--enable-crl-vfy")) + { + app.checkDependence("--enable-crl-vfy", "--verify", (opt_operation == DSO_verify)); + certVerifier.setCRLverification(OFTrue); + } + cmd.beginOptionBlock(); if (cmd.findOption("--std-passwd")) { @@ -907,12 +506,6 @@ int main(int argc, char *argv[]) opt_passwd = ""; } cmd.endOptionBlock(); - - cmd.beginOptionBlock(); - if (cmd.findOption("--pem-keys")) opt_keyFileFormat = X509_FILETYPE_PEM; - if (cmd.findOption("--der-keys")) opt_keyFileFormat = X509_FILETYPE_ASN1; - cmd.endOptionBlock(); - cmd.beginOptionBlock(); if (cmd.findOption("--profile-none")) { @@ -921,22 +514,41 @@ int main(int argc, char *argv[]) } if (cmd.findOption("--profile-base")) { + // the RSA base profile can be used on dataset and item level app.checkDependence("--profile-base", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); opt_profile = new SiBaseRSAProfile(); } if (cmd.findOption("--profile-creator")) { - app.checkDependence("--profile-creator", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + // the creator RSA profile only makes sense when applied on main dataset level + app.checkDependence("--profile-creator", "--sign", (opt_operation == DSO_sign)); opt_profile = new SiCreatorProfile(); } if (cmd.findOption("--profile-auth")) { - app.checkDependence("--profile-auth", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + // the authorization RSA profile only makes sense when applied on main dataset level + app.checkDependence("--profile-auth", "--sign", (opt_operation == DSO_sign)); opt_profile = new SiAuthorizationProfile(); + DCMSIGN_WARN( + "The Authorization RSA Digital Signature Profile requires that any\n" + "attributes whose values are verifiable by the technician or physician\n" + "(e.g., their values are displayed to the technician or physician) must\n" + "be included in the signature. Please assure this using --tag options." ); + } + if (cmd.findOption("--profile-sr")) + { + // the SR RSA profile only makes sense when applied on main dataset level + app.checkDependence("--profile-sr", "--sign", (opt_operation == DSO_sign)); + opt_profile = new SiStructuredReportingProfile(); + } + if (cmd.findOption("--profile-srv")) + { + // the SR RSA profile only makes sense when applied on main dataset level + app.checkDependence("--profile-srv", "--sign", (opt_operation == DSO_sign)); + opt_profile = new SiStructuredReportingVerificationProfile(); } cmd.endOptionBlock(); if (opt_profile == NULL) opt_profile = new SiNullProfile(); - cmd.beginOptionBlock(); if (cmd.findOption("--mac-ripemd160")) { @@ -968,22 +580,40 @@ int main(int argc, char *argv[]) app.checkDependence("--mac-sha512", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); opt_mac = new SiSHA512(); } - cmd.endOptionBlock(); if (opt_mac == NULL) opt_mac = new SiRIPEMD160(); + cmd.beginOptionBlock(); + if (cmd.findOption("--no-sig-purpose")) + { + app.checkDependence("--no-sig-purpose", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + opt_sigPurpose = SiSignaturePurpose::ESP_none; + } + if (cmd.findOption("--sig-purpose")) + { + app.checkDependence("--sig-purpose", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + OFCmdUnsignedInt val = 0; + app.checkValue(cmd.getValueAndCheckMinMax(val, 1, 18)); + opt_sigPurpose = SiSignaturePurpose::lookup(OFstatic_cast(size_t, val)); + if (opt_sigPurpose == SiSignaturePurpose::ESP_none) + { + // should never happen + DCMSIGN_WARN("unknown digital signature purpose code, ignoring."); + } + } + cmd.endOptionBlock(); + if (cmd.findOption("--tag-file")) { app.checkValue(cmd.getValue(opt_tagFile)); opt_tagList = new DcmAttributeTag(DCM_DataElementsSigned); - result = parseTextFile(opt_tagFile, *opt_tagList); + result = DcmSignatureHelper::parseTextFile(opt_tagFile, *opt_tagList); if (result > 0) { - OFLOG_FATAL(dcmsignLogger, "Error while reading tag file '" << opt_tagFile << "', giving up."); - return result; + DCMSIGN_FATAL("Error while reading tag file '" << opt_tagFile << "', giving up."); + goto cleanup; } } - if (cmd.findOption("--tag", 0, OFCommandLine::FOM_First)) { const char *current=NULL; @@ -991,31 +621,121 @@ int main(int argc, char *argv[]) do { app.checkValue(cmd.getValue(current)); - if (! addTag(current, *opt_tagList)) + if (! DcmSignatureHelper::addTag(current, *opt_tagList)) { - OFLOG_FATAL(dcmsignLogger, "unknown attribute tag '" << current << "'"); - return 10; + DCMSIGN_FATAL("unknown attribute tag '" << current << "'"); + result = EXITCODE_COMMANDLINE_SYNTAX_ERROR; + goto cleanup; } } while (cmd.findOption("--tag", 0, OFCommandLine::FOM_Next)); } - cmd.beginOptionBlock(); if (cmd.findOption("--format-new")) dcmEnableOldSignatureFormat.set(OFFalse); if (cmd.findOption("--format-old")) dcmEnableOldSignatureFormat.set(OFTrue); cmd.endOptionBlock(); + // timestamp command line options + cmd.beginOptionBlock(); + if (cmd.findOption("--timestamp-off")) + { + app.checkDependence("--timestamp-off", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + opt_timeStamp = NULL; + } + if (cmd.findOption("--timestamp-file")) + { + app.checkDependence("--timestamp-file", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); + app.checkValue(cmd.getValue(opt_ts_queryfile)); + app.checkValue(cmd.getValue(opt_ts_uidfile)); + opt_timeStamp = new SiTimeStampFS(); + opt_timeStamp->setTSQFilename(opt_ts_queryfile); + opt_timeStamp->setUIDFilename(opt_ts_uidfile); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ts-mac-sha256")) + { + app.checkDependence("--ts-mac-sha256", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_SHA256); + } + if (cmd.findOption("--ts-mac-sha384")) + { + app.checkDependence("--ts-mac-sha384", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_SHA384); + } + if (cmd.findOption("--ts-mac-sha512")) + { + app.checkDependence("--ts-mac-sha512", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_SHA512); + } + if (cmd.findOption("--ts-mac-ripemd160")) + { + app.checkDependence("--ts-mac-ripemd160", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_RIPEMD160); + } + if (cmd.findOption("--ts-mac-sha1")) + { + app.checkDependence("--ts-mac-sha1", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_SHA1); + } + if (cmd.findOption("--ts-mac-md5")) + { + app.checkDependence("--ts-mac-md5", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setMAC(EMT_MD5); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ts-use-nonce")) + { + app.checkDependence("--ts-use-nonce", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setNonce(OFTrue); + } + if (cmd.findOption("--ts-no-nonce")) + { + app.checkDependence("--ts-no-nonce", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setNonce(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ts-request-cert")) + { + app.checkDependence("--ts-request-cert", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setCertificateRequested(OFTrue); + } + if (cmd.findOption("--ts-no-cert")) + { + app.checkDependence("--ts-no-cert", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setCertificateRequested(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ts-no-policy")) + { + app.checkDependence("--ts-no-policy", "--timestamp-file", (opt_timeStamp != NULL)); + opt_timeStamp->setPolicyOID(NULL); + } + if (cmd.findOption("--ts-policy")) + { + app.checkDependence("--ts-policy", "--timestamp-file", (opt_timeStamp != NULL)); + app.checkValue(cmd.getValue(opt_ts_policyoid)); + opt_timeStamp->setPolicyOID(opt_ts_policyoid); + } + cmd.endOptionBlock(); + + // output command line options cmd.beginOptionBlock(); if (cmd.findOption("--write-xfer-same")) opt_oxfer = EXS_Unknown; if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; cmd.endOptionBlock(); - cmd.beginOptionBlock(); if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; cmd.endOptionBlock(); - if (cmd.findOption("--dump")) { app.checkDependence("--dump", "--sign or --sign-item", (opt_operation == DSO_sign) || (opt_operation == DSO_signItem)); @@ -1024,141 +744,135 @@ int main(int argc, char *argv[]) opt_dumpFile = fopen(fileName, "wb"); if (opt_dumpFile == NULL) { - OFLOG_FATAL(dcmsignLogger, "unable to create dump file '" << fileName << "'"); - return 10; + DCMSIGN_FATAL("unable to create dump file '" << fileName << "'"); + result = EXITCODE_CANNOT_WRITE_SUPPORT_FILE; + goto cleanup; } } } - /* print resource identifier */ - OFLOG_DEBUG(dcmsignLogger, rcsid << OFendl); - + DCMSIGN_DEBUG(rcsid << OFendl); /* make sure data dictionary is loaded */ if (!dcmDataDict.isDictionaryLoaded()) { - OFLOG_WARN(dcmsignLogger, "no data dictionary loaded, " + DCMSIGN_WARN("no data dictionary loaded, " << "check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); } - - // open inputfile + // open input file if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) { - OFLOG_FATAL(dcmsignLogger, "invalid filename: "); - return 1; + DCMSIGN_FATAL("invalid filename: "); + result = EXITCODE_NO_INPUT_FILES; + goto cleanup; } - - OFLOG_INFO(dcmsignLogger, "open input file " << opt_ifname); - - DcmFileFormat *fileformat = new DcmFileFormat; - - OFCondition sicond = fileformat->loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + DCMSIGN_INFO("open input file " << opt_ifname); + sicond = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); if (sicond.bad()) { - OFLOG_FATAL(dcmsignLogger, sicond.text() << ": reading file: " << opt_ifname); - return 1; + DCMSIGN_FATAL(sicond.text() << ": reading file: " << opt_ifname); + result = EXITCODE_CANNOT_READ_INPUT_FILE; + goto cleanup; } - - DcmDataset *dataset = fileformat->getDataset(); - - SiCertificate cert; - SiPrivateKey key; - + dataset = fileformat.getDataset(); if (opt_certfile) { sicond = cert.loadCertificate(opt_certfile, opt_keyFileFormat); if (sicond != EC_Normal) { - OFLOG_FATAL(dcmsignLogger, sicond.text() << ": while loading certificate file '" << opt_certfile << "'"); - return 1; + DCMSIGN_FATAL(sicond.text() << ": while loading certificate file '" << opt_certfile << "'"); + result = EXITCODE_CANNOT_READ_INPUT_FILE; + goto cleanup; } } - if (opt_keyfile) { if (opt_passwd) key.setPrivateKeyPasswd(opt_passwd); sicond = key.loadPrivateKey(opt_keyfile, opt_keyFileFormat); if (sicond != EC_Normal) { - OFLOG_FATAL(dcmsignLogger, sicond.text() << ": while loading private key file '" << opt_keyfile << "'"); - return 1; + DCMSIGN_FATAL(sicond.text() << ": while loading private key file '" << opt_keyfile << "'"); + result = EXITCODE_CANNOT_READ_INPUT_FILE; + goto cleanup; } } - // need to load all data into memory before signing the document, // otherwise the pixel data would be empty for compressed images - fileformat->loadAllDataIntoMemory(); - + fileformat.loadAllDataIntoMemory(); // select transfer syntax in which digital signatures are created opt_signatureXfer = dataset->getOriginalXfer(); - // use Little Endian Explicit for uncompressed files if ((opt_signatureXfer == EXS_LittleEndianImplicit) || (opt_signatureXfer == EXS_BigEndianExplicit)) opt_signatureXfer = EXS_LittleEndianExplicit; - // now do the real work switch (opt_operation) { case DSO_verify: - OFLOG_INFO(dcmsignLogger, "verifying all signatures."); - result = do_verify(dataset); - if (result != 0) return result; + DCMSIGN_INFO("verifying all signatures."); + result = DcmSignatureHelper::do_verify(dataset, certVerifier, opt_verificationPolicy, opt_timestampPolicy); + if (result != 0) goto cleanup; break; case DSO_sign: - OFLOG_INFO(dcmsignLogger, "create signature in main object."); - result = do_sign(dataset, key, cert, opt_mac, opt_profile, opt_tagList, opt_signatureXfer, opt_dumpFile); - if (result != 0) return result; + DCMSIGN_INFO("create signature in main object."); + result = DcmSignatureHelper::do_sign(dataset, key, cert, opt_mac, opt_profile, opt_tagList, opt_signatureXfer, opt_dumpFile, opt_sigPurpose, opt_timeStamp); + if (result != 0) goto cleanup; break; case DSO_signItem: - OFLOG_INFO(dcmsignLogger, "create signature in sequence item."); - result = do_sign_item(dataset, key, cert, opt_mac, opt_profile, opt_tagList, opt_location, opt_signatureXfer, opt_dumpFile); - if (result != 0) return result; + DCMSIGN_INFO("create signature in sequence item."); + result = DcmSignatureHelper::do_sign_item(dataset, key, cert, opt_mac, opt_profile, opt_tagList, opt_location, opt_signatureXfer, opt_dumpFile, opt_sigPurpose, opt_timeStamp); + if (result != 0) goto cleanup; + break; + case DSO_insertTimestamp: + DCMSIGN_INFO("inserting certified timestamp."); + result = DcmSignatureHelper::do_insert_ts(dataset, opt_timeStamp); + if (result != 0) goto cleanup; break; case DSO_remove: - OFLOG_INFO(dcmsignLogger, "removing signature from sequence item."); - result = do_remove(dataset, opt_location); - if (result != 0) return result; + DCMSIGN_INFO("removing signature from sequence item."); + result = DcmSignatureHelper::do_remove(dataset, opt_location); + if (result != 0) goto cleanup; break; case DSO_removeAll: - OFLOG_INFO(dcmsignLogger, "removing all signatures."); - result = do_remove_all(dataset); - if (result != 0) return result; + DCMSIGN_INFO("removing all signatures."); + result = DcmSignatureHelper::do_remove_all(dataset); + if (result != 0) goto cleanup; break; } - if (opt_dumpFile) { if (0 != fclose(opt_dumpFile)) { - OFLOG_FATAL(dcmsignLogger, "Error while closing dump file, content may be incomplete."); + DCMSIGN_FATAL("Error while closing dump file, content may be incomplete."); } opt_dumpFile = NULL; } - if (opt_ofname) { - OFLOG_INFO(dcmsignLogger, "create output file " << opt_ofname); - + DCMSIGN_INFO("create output file " << opt_ofname); if (opt_oxfer == EXS_Unknown) opt_oxfer = dataset->getOriginalXfer(); DcmXfer opt_oxferSyn(opt_oxfer); if (dataset->chooseRepresentation(opt_oxfer, NULL).bad() || (! dataset->canWriteXfer(opt_oxfer))) { - OFLOG_FATAL(dcmsignLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); - return 1; + DCMSIGN_FATAL("No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + result = EXITCODE_CANNOT_WRITE_OUTPUT_FILE; + goto cleanup; } - - sicond = fileformat->saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad)); + sicond = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad)); if (sicond.bad()) { - OFLOG_FATAL(dcmsignLogger, sicond.text() << ": writing file: " << opt_ofname); - return 1; + DCMSIGN_FATAL(sicond.text() << ": writing file: " << opt_ofname); + result = EXITCODE_CANNOT_WRITE_OUTPUT_FILE; + goto cleanup; } } +cleanup: + + delete opt_timeStamp; delete opt_mac; delete opt_profile; delete opt_tagList; - return 0; + return result; } #else /* WITH_OPENSSL */ @@ -1169,7 +883,7 @@ int main(int, char *[]) << OFFIS_CONSOLE_APPLICATION " requires the OpenSSL library." << OFendl << "This " OFFIS_CONSOLE_APPLICATION " has been configured and compiled without OpenSSL." << OFendl << "Please reconfigure your system and recompile if appropriate." << OFendl; - return 0; + return EXITCODE_NOOPENSSL; } #endif /* WITH_OPENSSL */ diff --git a/dcmsign/docs/dcmsign.dox b/dcmsign/docs/dcmsign.dox index bc3ee3ce..9b4f197b 100644 --- a/dcmsign/docs/dcmsign.dox +++ b/dcmsign/docs/dcmsign.dox @@ -9,6 +9,7 @@ external OpenSSL library. The main interface classes are: \li \b DcmSignature +\li \b DcmSignatureHelper \li \b SiSecurityProfile \li \b SiCertificate \li \b SiPrivateKey @@ -27,33 +28,30 @@ The following example shows how to verify all signatures in a DICOM file: DcmFileFormat fileformat; if (fileformat.loadFile("test.dcm").good()) { - int counter = 0; // counts the signatures in the DICOM file - int corrupt_counter = 0; // counts signatures that failed verification - - DcmDataset *dataset = fileformat.getDataset(); - DcmStack stack; // stores current location within file - DcmSignature signer; // signature handler - DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); - while (sigItem) // browse through items that contain digital signatures + // Load a root Certification Authority certificate from "ca_cert.pem" + // and declare it as trusted. All certificates issued by this CA will + // be considered trustworthy (if within their validity time). + SiCertificateVerifier certVerifier; + if (certVerifier.addTrustedCertificateFile("ca_cert.pem", + X509_FILETYPE_PEM).bad()) { - signer.attach(sigItem); // each item may contain multiple signatures - for (unsigned long l=0; l < signer.numberOfSignatures(); ++l) - { - if (signer.selectSignature(l).good()) - { - ++counter; - if (signer.verifyCurrent().bad()) // verify signature - corrupt_counter++; - } - } - signer.detach(); - sigItem = DcmSignature::findNextSignatureItem(*dataset, stack); + cerr << "unable to load CA certificate" << endl; + return; } - if (counter == 0) - cerr << "no signatures found in dataset." << endl; + + // Verify all signatures in the dataset, and verify the signer + // certificate against the root CA defined above. + // Fail if no signature is present in the dataset, but do not require + // any specific DICOM signature profile. Verify a secure timestamp + // if present, but do not fail signature verification if no timestamp + // is there. + int result = DcmSignatureHelper::do_verify(fileformat.getDataset(), + certVerifier, ESVP_requireSignature, ETVP_verifyTSIfPresent); + + if (result == 0) + std::cerr << "signature(s) found and successfully verified" << endl; else - cerr << counter << " signatures verified in dataset, " - << corrupt_counter << " corrupted." << endl; + std::cerr << "signature absent or verification failed" << endl; } \endcode @@ -63,10 +61,19 @@ The following example shows how to sign a DICOM file: DcmFileFormat fileformat; if (fileformat.loadFile("test.dcm").good()) { + // dataset to be signed DcmDataset *dataset = fileformat.getDataset(); - SiCreatorProfile profile; // select the "RSA Creator Profile" + + // select transfer syntax in which digital signature will be created + E_TransferSyntax xfer = dataset->getOriginalXfer(); + + // use Little Endian Explicit for uncompressed files + if ((xfer == EXS_LittleEndianImplicit) || + (xfer == EXS_BigEndianExplicit)) + xfer = EXS_LittleEndianExplicit; + + SiCreatorProfile profile; // use the "RSA Creator Profile" SiRIPEMD160 mac; // use RIPEMD160 as MAC algorithm - DcmSignature signer; // signature handler SiCertificate cert; // our certificate if (cert.loadCertificate("certificate.pem", X509_FILETYPE_PEM).bad()) { @@ -79,11 +86,21 @@ if (fileformat.loadFile("test.dcm").good()) cerr << "unable to load private key" << endl; return; } - signer.attach(dataset); // connect handler to data set - if (signer.createSignature(key, cert, mac, profile).good()) - { - fileformat.saveFile("test_signed.dcm"); // write back - } + + // list of attributes to be signed. It can remain empty here + // since we're using the RSA Creator Profile to determine the + // list of attributes that needs to be signed + DcmAttributeTag tags; + + // now create the signature + int result = DcmSignatureHelper::do_sign(dataset, + key, cert, &mac, &profile, &tags, xfer, NULL, + SiSignaturePurpose::ESP_none, NULL); + + if (result == 0) + std::cerr << "signature successfully created" << endl; + else + std::cerr << "signature creation failed" << endl; } \endcode diff --git a/dcmsign/docs/dcmsign.man b/dcmsign/docs/dcmsign.man index 5acae9a7..ceb1766d 100644 --- a/dcmsign/docs/dcmsign.man +++ b/dcmsign/docs/dcmsign.man @@ -94,6 +94,14 @@ input transfer syntax: -ti --read-xfer-implicit read with implicit VR little endian TS + +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known \endverbatim \subsection dcmsign_signature_commands signature commands @@ -107,6 +115,10 @@ input transfer syntax: +si --sign-item [k]eyfile, [c]ertfile, [i]tem location: string create signature in sequence item + +t --insert-timestamp ts[q]file, ts[r]file [u]idfile: string + insert certified timestamp from ts response r + from timestamp query q at signature UID u + +r --remove [s]ignature UID: string remove signature @@ -114,7 +126,83 @@ input transfer syntax: remove all signatures from data set \endverbatim -\subsection dcmsign_signature_creation_options signature creation options (only with --sign or --sign-item): +\subsection dcmsign_general_signature_options general signature options +\verbatim +key and certificate file format: + + -pem --pem-keys + read keys/certificates as PEM file (default) + + -der --der-keys + read keys/certificates as DER file + +signature format: + + -fn --format-new + use correct DICOM signature format (default) + + -fo --format-old + use old (pre-3.5.4) DCMTK signature format, non-conformant + if signature includes compressed pixel data. This option should + only be used to verify signatures in the old format. +\endverbatim + +\subsection dcmsign_signature_verification_options signature verification options (only with --verify) +\verbatim +signature verification: + + +rv --verify-if-present + verify signatures if present, pass otherwise + (default) + + +rg --require-sig + fail if no signature at all is present + + +rc --require-creator + fail if no creator RSA signature is present + + +ru --require-auth + fail if no auth RSA signature is present + + +rs --require-sr + fail if no SR RSA signature is present + +timestamp verification: + + +tv --verify-ts + verify certified timestamp if present (default) + + -tv --ignore-ts + ignore certified timestamps + + +tr --require-ts + fail if no certified timestamp is present + +certification authority: + + +cf --add-cert-file + [f]ilename: string + add trusted certificate file to cert store + + +uf --add-ucert-file + [f]ilename: string + add untrusted intermediate certificate file + + +cd --add-cert-dir + [d]irectory: string + add certificates in d to cert store + + +cr --add-crl-file + [f]ilename: string + add certificate revocation list file + (implies --enable-crl-vfy) + + +cl --enable-crl-vfy + enable certificate revocation list verification + +\endverbatim + +\subsection dcmsign_signature_creation_options signature creation options (only with --sign or --sign-item) \verbatim private key password: @@ -127,14 +215,6 @@ private key password: -pw --null-passwd use empty string as password -key and certificate file format: - - -pem --pem-keys - read keys/certificates as PEM file (default) - - -der --der-keys - read keys/certificates as DER file - digital signature profile: -pf --profile-none @@ -149,6 +229,12 @@ digital signature profile: +pa --profile-auth enforce authorization signature profile + +pr --profile-sr + enforce SR RSA signature profile + + +pv --profile-srv + enforce SR RSA signature profile (verification) + MAC algorithm: +mr --mac-ripemd160 @@ -160,6 +246,27 @@ MAC algorithm: +mm --mac-md5 use MD 5 + +m2 --mac-sha256 + use SHA-256 + + +m3 --mac-sha384 + use SHA-384 + + +m5 --mac-sha512 + use SHA-512 + +signature purpose: + + +lp --list-purposes + show list of signature purpose codes and exit + + -sp --no-sig-purpose + do not add signature purpose (default) + + +sp --sig-purpose + [p]urpose code: integer (1..18) + add digital signature purpose code p + tag selection: -t --tag @@ -170,14 +277,61 @@ tag selection: -tf --tag-file [f]ilename: string read list of tags from text file -signature format: +\endverbatim - -fn --format-new - use correct DICOM signature format (default) +\subsection dcmsign_timestamp_creation_options timestamp creation options (only with --sign or --sign-item) +\verbatim +timestamp creation: - -fo --format-old - use old (pre-3.5.4) DCMTK signature format, non-conformant - if signature includes compressed pixel data + -ts --timestamp-off + do not create timestamp (default) + + +ts --timestamp-file [t]sq-filename, [u]id-filename: string + create timestamp query file t and uid file u + +timestamp MAC algorithm (only with --timestamp-file): + + +tm2 --ts-mac-sha256 + use SHA-256 (default) + + +tm3 --ts-mac-sha384 + use SHA-384 + + +tm5 --ts-mac-sha512 + use SHA-512 + + +tmr --ts-mac-ripemd160 + use RIPEMD 160 + + +tms --ts-mac-sha1 + use SHA-1 (not recommended) + + +tmm --ts-mac-md5 + use MD5 (not recommended) + +timestamp query nonce options (only with --timestamp-file): + + +tn --ts-use-nonce + include random nonce (default) + + -tn --ts-no-nonce + do not include nonce + +timestamp certificate inclusion options (only with --timestamp-file): + + +tc --ts-request-cert + request TSA certificate in timestamp (default) + + -tc --ts-no-cert + do not request TSA certificate in timestamp + +timestamp policy options (only with --timestamp-file): + + -tp --ts-no-policy + do not specify ts policy (default) + + +tp --ts-policy [p]olicy-OID: string + request timestamp policy p \endverbatim \subsection dcmsign_output_options output options @@ -219,21 +373,24 @@ The \b dcmsign utility reads and writes a number of files and file formats which are described in this section. Public Key Certificates are expected in X.509v3 format, either with PEM or DER -encoding. The dcmsign utility currently supports RSA and DSA public keys, +encoding. The \b dcmsign utility currently supports RSA and DSA public keys, although only RSA keys are defines in the Security Profiles of the DICOM standard. Private Keys are expected in PEM or DER encoding. PEM is recommended (and -default) because this allows one to keep private keys in encrypted form. Command -line options control the behavior of \b dcmsign when an encrypted PEM key is -opened (see above). In general it is not recommended to specify the encryption -password in the command line because the command line may be visible to other -processes in the system, e.g. "ps -ef". +default) because this allows one to keep private keys in encrypted form. +Command line options control the behavior of \b dcmsign when an encrypted PEM +key is opened (see above). In general it is not recommended to specify the +encryption password in the command line because the command line may be visible +to other processes in the system, e.g. "ps -ef". -The list of data elements to sign can either be read from a file or specified -on the command line or both (in this case the keys are combined). +By default, \b dcmsign will create a signature covering all data elements in the +dataset or item. This default can be overridden by explicitly specifying a list +of data elements (attribute tags). This list can either be read from a file or +specified on the command line or both (in this case the attribute tags are +combined). -On the command line, attribute keys are specified as +On the command line, attribute tags are specified as \verbatim --tag "gggg,eeee" where gggg and eeee are the hexadecimal group @@ -243,9 +400,13 @@ On the command line, attribute keys are specified as \endverbatim When attribute tags are read from file with the \e --tag-file option, a plain -text file of max. 64 kbyte is expected. Tags within the file are either -symbolic names from the data dictionary or have the format (gggg,eeee) (with -braces). Tags are separated by one or more whitespace characters. +text file is expected. Tags within the file are either symbolic names from the +data dictionary or have the format (gggg,eeee) (with braces). Tags are +separated by one or more whitespace characters. + +The currently selected digital signature profile may specify additional +attribute tags required to be included in the signature, which will be silently +added. The \e --sign-item operation requires a location string that describes in which sequence item a signature is to be created. The location string has the @@ -269,6 +430,52 @@ ReferencedImageSequence (0008,1140) which is located in the first item of the ReferencedSeriesSequence (0008,1115) which is located in the main DICOM dataset. +\subsection dcmsign_certified_timestamps Certified Timestamps + +Starting with release 3.6.6, \b dcmsign offers support for certified timestamps +according to RFC 3161. For now, the tool does not implement any of the network +protocols defined in RFC 3161 for communicating with a timestamp authority +(TSA), but it can write a timestamp query (TSQ) during signature creation, and +the new command \e --insert-timestamp will read a timestamp response (TSR) from +file and add it to the DICOM digital signature. Since a DICOM file can contain +multiple signatures, a "UID file" (which contains the Digital Signature UID) +is used to identify the signature to which the TSR should be added. The +\b dcmsign tool will also perform various consistency checks before storing the +timestamp. + +During signature verification, the presence of a certified timestamp will be +detected and the timestamp will also be verified unless option \e --ignore-ts +was used. Signature verification and timestamp verification use a common +certificate store to check the certificates of the DICOM signature and the +timestamp. This store can be populated with the options \e --add-cert-file and +\e --add-cert-dir, which both add trusted CA certificates, \e --add-ucert-file, +which adds an untrusted intermediate CA certificate, and \e --add-crl-file, +which adds a certificate revocation list. + +\subsection dcmsign_hashed_certificate_directories Hashed Certificate Directories + +Instead of adding CA certificates and certificate revocation lists (CRLs) +manually using \e --add-cert-file and \e --add-crl-file, the user can set-up +a directory where \b dcmsign will look-up and load certificates and CRLs from +as needed, using \e --add-cert-dir. + +Th directory should contain one certificate or CRL per file in PEM format, +with a filename of the form hash.N for a certificate, or hash.rN for a CRL. +The hash is the value returned by + + openssl x509 -hash -noout -in \ (for a certificate) + openssl crl -hash -noout -in \ (for a CRL) + +The .N or .rN suffix is a sequence number that starts at zero, and is +incremented consecutively for each certificate or CRL with the same hash value. +Gaps in the sequence numbers are not supported, it is assumed that there are no +more objects with the same hash beyond the first missing number in the sequence. + +CRLs will only be verified when option \e --enable-crl-vfy is specified. In +this case, \b dcmsign will expect a CRL to be present for each CA and will fail +signature verification if no CRL can be found for the CA that issued the signer +certificate. + \section dcmsign_logging LOGGING The level of logging output of the various command line tools and underlying @@ -310,6 +517,53 @@ allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \/dumppat.txt). +\section dcmsign_exit_codes EXIT CODES + +The \b dcmsign utility uses the following exit codes when terminating. This +enables the user to check for the reason why the application terminated. + +\subsection dcmsign_exit_codes_general general +\verbatim +EXITCODE_NO_ERROR 0 +EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 +EXITCODE_NOOPENSSL 5 +\endverbatim + +\subsection dcmsign_exit_codes_input_file_errors input file errors +\verbatim +EXITCODE_CANNOT_READ_INPUT_FILE 20 +EXITCODE_NO_INPUT_FILES 21 +EXITCODE_CANNOT_READ_TAG_FILE 30 +EXITCODE_CANNOT_READ_TSQ_FILE 31 +EXITCODE_CANNOT_READ_TSR_FILE 32 +EXITCODE_CANNOT_READ_UID_FILE 33 +\endverbatim + +\subsection dcmsign_exit_codes_output_file_errors output file errors +\verbatim +EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 +EXITCODE_CANNOT_WRITE_SUPPORT_FILE 46 +\endverbatim + +\subsection dcmsign_exit_codes_processing_errors processing errors +\verbatim +EXITCODE_CANNOT_ACCESS_SIGNATURE 80 +EXITCODE_CANNOT_ACCESS_TS 81 +EXITCODE_CANNOT_INSERT_TS 82 +EXITCODE_SIGNATURE_REMOVAL_FAILED 83 +EXITCODE_SIGNATURE_UID_NOT_FOUND 84 +EXITCODE_SIGNATURE_CREATION_FAILED 85 +EXITCODE_SYNTAX_ERROR_IN_TAG_FILE 86 +EXITCODE_TS_CONSISTENCY_CHECK_FAILED 87 +\endverbatim + +\subsection dcmsign_exit_codes_application_errors application specific errors +\verbatim +EXITCODE_NO_SIGNATURES_PRESENT 100 +EXITCODE_SIGNATURE_VERIFICATION_FAILED 101 +EXITCODE_SIGNATURE_VERIFICATION_POLICY 102 +\endverbatim + \section dcmsign_environment ENVIRONMENT The \b dcmsign utility will attempt to load DICOM data dictionaries specified @@ -328,6 +582,6 @@ It is an error if no data dictionary can be loaded. \section dcmsign_copyright COPYRIGHT -Copyright (C) 2000-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 2000-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmsign/include/dcmtk/dcmsign/dcsighlp.h b/dcmsign/include/dcmtk/dcmsign/dcsighlp.h new file mode 100644 index 00000000..f253a91b --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/dcsighlp.h @@ -0,0 +1,222 @@ +/* + * + * Copyright (C) 1998-2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: DcmSignatureHelper + * + */ + +#ifndef DCMSIGHLP_H +#define DCMSIGHLP_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for Uint32 */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ +#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ +#include "dcmtk/dcmsign/sidefine.h" /* for DCMTK_DCMSIGN_EXPORT */ +#include "dcmtk/dcmsign/sipurpos.h" /* for class SiSignaturePurpose */ +#include "dcmtk/dcmsign/sitypes.h" /* for dcmsign enums */ + +#ifdef WITH_OPENSSL + +class DcmAttributeTag; +class DcmItem; +class DcmStack; +class DcmTagKey; +class SiCertificate; +class SiMAC; +class SiPrivateKey; +class SiSecurityProfile; +class SiTimeStamp; +class SiTimeStampFS; +class SiCertificateVerifier; +class DcmSignature; + +/** this class provides helper functions for creating and verifying + * digital signatures. It encapsulates most of the code that was part + * of the main command line program "dcmsign" in prior DCMTK releases. + * @remark this class is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +class DCMTK_DCMSIGN_EXPORT DcmSignatureHelper +{ +public: + + /// default constructor + DcmSignatureHelper(); + + /// destructor + virtual ~DcmSignatureHelper(); + + /** locate a specific item within the given dataset. + * @param dataset dataset to be searched + * @param location location string. Format is "sequence[item]{.sequence[item]}*" + * Where sequence can be (gggg,eeee) or a dictionary name and items + * within sequences are counted from zero. + * @return pointer to the item searched if found, NULL otherwise + */ + static DcmItem *locateItemforSignatureCreation(DcmItem& dataset, const char *location); + + /** read a list of attributes from a text file. + * The attributes can be in the form (gggg,eeee) or can be dictionary names, + * separated by arbitrary whitespace. + * @param filename file to be read from + * @param tagList attribute tags are added to this list + * @return 0 if successful, a program exit code otherwise + */ + static int parseTextFile(const char *filename, DcmAttributeTag& tagList); + + /** read an attribute tag in the form "gggg,eeee" and adds it + * to the given attribute tag list + * @param c input string + * @param tagList list to be added to + * @return true if successful, false otherwise + */ + static OFBool addTag(const char *c, DcmAttributeTag& tagList); + + /** print the location stack into the given stack. + * It is assumed that the stack top is a DigitalSignatureSequence which is not printed + * and that the stack bottom is the main dataset, which is also not printed. + * @param stack search stack, as returned by DcmSignature::findFirstSignatureItem() etc. + * @param str printable text returned in this string. + */ + static void printSignatureItemPosition(DcmStack& stack, OFString& str); + + /** perform a signature operation on a given dataset + * @param dataset to sign + * @param key private key for signature + * @param cert certificate for signature + * @param opt_mac MAC for signature + * @param opt_profile security profile for signature + * @param opt_tagList list of attribute tags, may be NULL + * @param opt_signatureXfer signature transfer syntax + * @param dumpFile file to dump the byte stream to + * @param opt_sigPurpose signature purpose + * @param timeStamp pointer to timestamp client, may be NULL + * @return 0 if successful, a program exit code otherwise + */ + static int do_sign( + DcmItem *dataset, + SiPrivateKey& key, + SiCertificate& cert, + SiMAC *opt_mac, + SiSecurityProfile *opt_profile, + DcmAttributeTag *opt_tagList, + E_TransferSyntax opt_signatureXfer, + FILE *dumpFile, + SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose, + SiTimeStamp *timeStamp = NULL); + + /** performs a signature operation on a sub-item within a dataset + * @param dataset in which to sign + * @param key private key for signature + * @param cert certificate for signature + * @param opt_mac MAC for signature + * @param opt_profile security profile for signature + * @param opt_tagList list of attribute tags, may be NULL + * @param location location string. Format is "sequence[item]{.sequence[item]}*" + * Where sequence can be (gggg,eeee) or a dictionary name and items + * within sequences are counted from zero. + * @param opt_signatureXfer signature transfer syntax + * @param dumpFile file to dump the byte stream to + * @param opt_sigPurpose signature purpose + * @param timeStamp pointer to timestamp client, may be NULL + * @return 0 if successful, a program exit code otherwise + */ + static int do_sign_item( + DcmItem *dataset, + SiPrivateKey& key, + SiCertificate& cert, + SiMAC *opt_mac, + SiSecurityProfile *opt_profile, + DcmAttributeTag *opt_tagList, + const char *opt_location, + E_TransferSyntax opt_signatureXfer, + FILE *dumpFile, + SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose, + SiTimeStamp *timeStamp = NULL); + + /** verify all signatures in the given dataset and print results to stdout. + * @param dataset dataset to verify + * @param certVerifier certification verifier helper object + * @param verificationPolicy signature verification policy + * @param timstampPolicy timestamp verification policy + * @return 0 if successful, a program exit code otherwise + */ + static int do_verify( + DcmItem *dataset, + SiCertificateVerifier& certVerifier, + E_SignatureVerificationPolicy verificationPolicy, + E_TimestampVerificationPolicy timstampPolicy); + + /** insert certified timestamp from file. + * @param dataset in which to add timestamp + * @param timeStamp handler, must not be NULL + */ + static int do_insert_ts(DcmItem *dataset, SiTimeStampFS *timeStamp); + + /** remove all signatures from the given dataset, print action details. + * @param dataset dataset to modify + * @return 0 if successful, a program exit code otherwise + */ + static int do_remove_all(DcmItem *dataset); + + /** remove the signature with the given UID from the dataset, print action details. + * @param dataset dataset to modify + * @param opt_location Digital Signature UID of the signature to remove + * @return 0 if successful, a program exit code otherwise + */ + static int do_remove( + DcmItem *dataset, + const char *opt_location); + +private: + + /** scans a token from the given string and returns it. Ignores leading whitespace. + * @param c string to parse + * @param pos position within string, modified after successful scan + * @param key tag key returned in this parameter if return value is "tag key". + * @param idx index returned in this parameter if return value is "index". + * @return -1 for "EOF", 0 for "parse error", 1 for "tag key", 2 for "index", 3 for "period" + */ + static int readNextToken(const char *c, int& pos, DcmTagKey& key, Uint32& idx); + + /** reads a complete text file (max 64K) into a memory block + * and returns a pointer to the memory block. + * memory must be freed by caller. + * @param filename file to be read + * @return pointer to memory block if successful, NULL otherwise. + */ + static char *readTextFile(const char *filename); + + /** print the details of the current signature to the logger + * @param sig signature object + * @param stack position of the signature object in the dataset + * @param count number of the signature (counter) + */ + static void printSignatureDetails(DcmSignature& sig, DcmStack& stack, int count); + + /** print the details of the timestamp for the current signature to the logger + * @param sig signature object + * @param tsPolicy timestamp verification policy + */ + static void printTimestampDetails(DcmSignature& sig, E_TimestampVerificationPolicy tsPolicy); + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/dcsignat.h b/dcmsign/include/dcmtk/dcmsign/dcsignat.h index 9da04117..114029b7 100644 --- a/dcmsign/include/dcmtk/dcmsign/dcsignat.h +++ b/dcmsign/include/dcmtk/dcmsign/dcsignat.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,30 +24,33 @@ #define DCMSIGN_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL -#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ +#include "dcmtk/dcmsign/sitypes.h" +#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ +#include "dcmtk/dcmsign/sipurpos.h" /* for E_SignaturePurposeType */ #define INCLUDE_CSTDIO #include "dcmtk/ofstd/ofstdinc.h" +class DcmAttributeTag; +class DcmDateTime; class DcmItem; -class DcmStack; class DcmSequenceOfItems; -class DcmAttributeTag; +class DcmStack; +class DcmTagKey; class SiPrivateKey; class SiCertificate; class SiSecurityProfile; class SiMAC; class SiTimeStamp; -/** this class provides the main interface to the dcmsign module - it allows - * to create, examine and verify digital signatures in DICOM datasets or - * items. The methods in this class do not handle digital signatures - * embedded in sequence items within the dataset, other than providing - * helper functions that allow to locate and attach the sub-items +/** this class provides the main interface to the dcmsign module - it allows + * to create, examine and verify digital signatures in DICOM datasets or + * items. The methods in this class do not handle digital signatures + * embedded in sequence items within the dataset, other than providing + * helper functions that allow to locate and attach the sub-items * separately. * @remark this class is only available if DCMTK is compiled with * OpenSSL support enabled. @@ -63,18 +66,18 @@ public: /// default constructor DcmSignature(); - + /// destructor virtual ~DcmSignature(); /** attaches a DICOM dataset or item to the signature object. * The dataset is detached by a call to detach() or by destruction - * of the signature object. This object may modify but never deletes + * of the signature object. This object may modify but never deletes * an attached dataset. * @param dataset dataset or item to be attached */ - void attach(DcmItem *dataset); - + void attach(DcmItem *dataset); + /** detaches an attached DICOM dataset from the signature object. */ void detach(); @@ -94,18 +97,20 @@ public: * i.e. all signable attributes in the data set are signed. * @param timeStamp pointer to time stamp client used to create timestamps * for the digital signature. + * @param sigPurpose digital signature purpose * @return status code */ OFCondition createSignature( - SiPrivateKey& key, - SiCertificate& cert, + SiPrivateKey& key, + SiCertificate& cert, SiMAC& mac, - SiSecurityProfile& profile, + SiSecurityProfile& profile, E_TransferSyntax xfer=EXS_LittleEndianExplicit, const DcmAttributeTag *tagList=NULL, - SiTimeStamp *timeStamp=NULL); + SiTimeStamp *timeStamp=NULL, + SiSignaturePurpose::E_SignaturePurposeType sigPurpose=SiSignaturePurpose::ESP_none); - /** returns the number of signatures in the dataset. Does not count + /** returns the number of signatures in the dataset. Does not count * signatures embedded in sequence items within the dataset. */ unsigned long numberOfSignatures(); @@ -121,7 +126,7 @@ public: * @return status code */ OFCondition selectSignature(unsigned long i); - + /** verifies the current signature. * Current signature must be selected with selectSignature(). * @return SI_EC_Normal if signature is complete and valid, an error code @@ -166,6 +171,13 @@ public: */ OFCondition getCurrentSignatureDateTime(OFString& str); + /** returns a pointer to the object representing Signature Date/Time + * of the current signature. + * Current signature must be selected with selectSignature(). + * @return pointer to signature datetime if present, NULL otherwise + */ + DcmDateTime *getCurrentSignatureDateTime(); + /** returns the Data Elements Signed attribute of the current signature if present. * Current signature must be selected with selectSignature(). * If a valid signature is selected but the signature does not contain @@ -176,13 +188,45 @@ public: */ OFCondition getCurrentDataElementsSigned(DcmAttributeTag& desig); + /** returns the signature purpose code of the current signature if present. + * Current signature must be selected with selectSignature(). + * If a valid signature is selected but the signature does not contain + * a valid SignaturePurposeCodeSequence, this method returns an error code. + * @param codeValue signature purpose code value returned in this parameter upon success + * @param codeMeaning signature purpose code meaning returned in this parameter upon success + * @param codingSchemeDesignator signature purpose coding scheme designator returned in this parameter upon success + * @return status code + */ + OFCondition getCurrentSignaturePurpose(OFString& codeValue, OFString& codeMeaning, OFString& codingSchemeDesignator); + + /** verifies whether the currently selected signature within the + * currently attached dataset matches the requirements of the + * given signature profile. + * @param sprof security profile + * @return EC_Normal if signature matches, an error code otherwise + */ + OFCondition verifySignatureProfile(SiSecurityProfile &sprof); + /** returns the certificate of the current signature if present. * Current signature must be selected with selectSignature(). * May return NULL if certificate is unavailable. * @return pointer to current certificate, NULL if unavailable. */ SiCertificate *getCurrentCertificate(); - + + /** returns the certified timestamp of the current signature if present. + * Current signature must be selected with selectSignature(). + * May return NULL if timestamp is unavailable. + * @return pointer to current timestamp, NULL if unavailable. + */ + SiTimeStamp *getCurrentTimestamp(); + + /** returns the item of the DigitalSignaturesSequence selected by the last call + * to selectSignature(), or NULL if no signature has been selected. + * @return pointer to current signature item, may be NULL + */ + DcmItem *getSelectedSignatureItem(); + /** dump all data that is fed into the MAC algorithm into the given file, * which must be opened and closed by caller. * @param f pointer to file already opened for writing; may be NULL. @@ -190,7 +234,7 @@ public: void setDumpFile(FILE *f); /** recursively browses through the given dataset and searches the first - * occurence of the DigitalSignaturesSequence. If found, returns + * occurrence of the DigitalSignaturesSequence. If found, returns * a pointer to the Item in which the sequence is contained. * @param item dataset to be browsed * @param stack search stack, must be passed to findNextSignatureItem() later on. @@ -199,7 +243,7 @@ public: static DcmItem *findFirstSignatureItem(DcmItem& item, DcmStack& stack); /** recursively browses through the given dataset and searches the next - * occurence of the DigitalSignaturesSequence. If found, returns + * occurrence of the DigitalSignaturesSequence. If found, returns * a pointer to the Item in which the sequence is contained. * @param item dataset to be browsed * @param stack search stack as returned by findFirstSignatureItem() or the last call to this method. @@ -207,6 +251,16 @@ public: */ static DcmItem *findNextSignatureItem(DcmItem& item, DcmStack& stack); + /** check a DER encoded ASN.1 SEQUENCE structure for a possible pad byte + * and, if a pad byte is detected, remove it by decreasing buflen. + * This will work for SEQUENCEs with one byte and two byte encoding + * (i.e. max 64 kBytes). + * @param buf pointer to DER encoded ASN.1 data + * @param buflen length of buffer pointed to, in bytes. The variable is + * decreased by one if a pad byte is detected. + */ + static void adjustASN1SequenceLength(const unsigned char *buf, unsigned long& buflen); + private: /// private undefined copy constructor @@ -225,13 +279,31 @@ private: * @return status code */ OFCondition allocateMACID(Uint16& newID); - + /** searches a given item for the DCM_MACIDnumber element and returns - * its value if present, otherwise returns 0. + * its value if present * @param item item to be searched - * @return MAC ID number in item or zero if absent. + * @param macid MAC ID returned in this parameter upon success + * @return EC_Normal if successful, an error code otherwise */ - static Uint16 getMACIDnumber(DcmItem &item); + static OFCondition getMACIDnumber(DcmItem &item, Uint16& macid); + + /** checks if all tags from tagList are present in tagListOut, + * which is the list of attribute tags actually included in a signature, + * including tags added due to a signature profile, and without tags + * that were absent in the dataset. + * @param tagList list of attribute tags that should be present in the signature, may be NULL + * @param tagListOut list of attribute tags actually present in the signature, must not be NULL + * @return EC_Normal if check succeeds, an error code otherwise + */ + static OFCondition checkListOfSignedTags(const DcmAttributeTag *tagList, const DcmAttributeTag *tagListOut); + + /** checks if the given tag key is present in tagList + * @param tag tag key + * @param tagList list of tag keys + * @return OFTrue of tag is present in tagList, OFFalse otherwise + */ + static OFBool inTagList(const DcmTagKey &tag, const DcmAttributeTag& tagList); /** returns the current date and time as a DICOM DT string. * @param str date/time returned in this string. @@ -257,8 +329,10 @@ private: DcmItem *selectedMacParametersItem; /// pointer to certificate for currently selected signature item - SiCertificate *selectedCertificate; - + SiCertificate *selectedCertificate; + + /// pointer to certified timestamp for currently selected signature item + SiTimeStamp *selectedTimestamp; }; #endif diff --git a/dcmsign/include/dcmtk/dcmsign/sialgo.h b/dcmsign/include/dcmtk/dcmsign/sialgo.h index 2b3d39ac..df9adfb6 100644 --- a/dcmsign/include/dcmtk/dcmsign/sialgo.h +++ b/dcmsign/include/dcmtk/dcmsign/sialgo.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,10 @@ #define SIALGO_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" #include "dcmtk/ofstd/oftypes.h" /** diff --git a/dcmsign/include/dcmtk/dcmsign/siautopr.h b/dcmsign/include/dcmtk/dcmsign/siautopr.h index 9f37e834..3c74e8a0 100644 --- a/dcmsign/include/dcmtk/dcmsign/siautopr.h +++ b/dcmsign/include/dcmtk/dcmsign/siautopr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,11 @@ #define SIAUTOPR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sibrsapr.h" /* for SiBaseRSAProfile */ #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sibrsapr.h" /* for SiBaseRSAProfile */ + /** Authorization Digital Signature Profile * @remark this class is only available if DCMTK is compiled with * OpenSSL support enabled. @@ -37,17 +38,44 @@ class DCMTK_DCMSIGN_EXPORT SiAuthorizationProfile: public SiBaseRSAProfile public: /// default constructor - SiAuthorizationProfile() { } + SiAuthorizationProfile(); /// destructor virtual ~SiAuthorizationProfile() { } /** checks whether an attribute with the given tag is required to be signed - * for the current security profile. + * for the current security profile if the attribute is present in the dataset * @param key tag key to be checked * @return true if required, false otherwise. */ - virtual OFBool attributeRequired(const DcmTagKey& key) const; + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; + + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const; + +private: + + /// flag indicating whether or not the signature dataset contains the raw data module + OFBool containsRawData_; }; diff --git a/dcmsign/include/dcmtk/dcmsign/sibrsapr.h b/dcmsign/include/dcmtk/dcmsign/sibrsapr.h index 423e9b33..0ad911e2 100644 --- a/dcmsign/include/dcmtk/dcmsign/sibrsapr.h +++ b/dcmsign/include/dcmtk/dcmsign/sibrsapr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,11 @@ #define SIBRSAPR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sisprof.h" /* for SiSecurityProfile */ #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sisprof.h" /* for SiSecurityProfile */ + /** Base RSA Digital Signature Profile * @remark This class is only available if DCMTK is compiled with * OpenSSL support enabled. @@ -41,7 +42,7 @@ public: /// destructor virtual ~SiBaseRSAProfile() { } - + /** checks whether the given MAC type can be used with this security profile. * @param macType MAC type to be checked * @return true if MAC type is allowable for this profile, false otherwise. @@ -61,11 +62,18 @@ public: virtual OFBool isAllowableTransferSyntax(E_TransferSyntax xfer) const; /** checks whether an attribute with the given tag is required to be signed - * for the current security profile. + * for the current security profile if the attribute is present in the dataset * @param key tag key to be checked * @return true if required, false otherwise. */ - virtual OFBool attributeRequired(const DcmTagKey& key) const; + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; /** checks whether an attribute with the given tag must not be signed * for the current security profile. @@ -74,6 +82,21 @@ public: */ virtual OFBool attributeForbidden(const DcmTagKey& key) const; + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const; + }; #endif diff --git a/dcmsign/include/dcmtk/dcmsign/sicert.h b/dcmsign/include/dcmtk/dcmsign/sicert.h index c587f30b..4aefc687 100644 --- a/dcmsign/include/dcmtk/dcmsign/sicert.h +++ b/dcmsign/include/dcmtk/dcmsign/sicert.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,28 +24,37 @@ #define SICERT_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" #include "dcmtk/ofstd/ofstring.h" /* for class OFString */ class DcmItem; class SiAlgorithm; +class OFDateTime; struct x509_st; +struct asn1_string_st; typedef struct x509_st X509; +typedef struct asn1_string_st ASN1_STRING; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; /** a class representing X.509 public key certificates. * @remark this class is only available if DCMTK is compiled with * OpenSSL support enabled. */ class DCMTK_DCMSIGN_EXPORT SiCertificate -{ +{ public: /// default constructor SiCertificate(); - + + /** constructor + * @param cert pointer to OpenSSL X509 object. Ownership is transferred to the SiCertificate instance + */ + SiCertificate(X509 *cert); + ///destructor virtual ~SiCertificate(); @@ -69,11 +78,11 @@ public: * @return dcmdata OFCondition status code */ OFCondition write(DcmItem& item); - + /** returns the type of public key stored in this certificate */ E_KeyType getKeyType(); - + /** creates an SiAlgorithm object for the public key contained in this certificate. * If no certificate loaded or operation fails, returns NULL. * New SiAlgorithm object must be deleted by caller. @@ -124,11 +133,72 @@ public: */ long getCertKeyBits(); - /** returns a pointer to the raw certificate structure or NULL if no + /** returns the name of the elliptic curve used in the certificate. + * @return NULL if the certificate is not of elliptic curve type, + * "unnamed curve" if the curve name has not been stored in the certificate, + * or the short name of the elliptic curve if available. + */ + const char *getCertCurveName(); + + /** checks if the length of the public key in the certificate is too short + * and must be considered weak. Currently, an RSA or DSA key with less than + * 1024 bits and an ECDSA key with less than 256 bits are considered weak. + * @return OFTrue if key is weak, OFFalse otherwise. + */ + OFBool isWeakKey(); + + /** checks if the length of the public key in the certificate is too short + * and must be considered weak, and if so, prints a warning to the logger. + */ + void checkForWeakKey(); + + /** returns a pointer to the raw certificate structure or NULL if no * certificate present. Should not be called by users of this library. */ X509 *getRawCertificate(); + /** returns true if the certificate expires before the given date. + * @param date a string in the format YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ + * (where Z represents the letter 'Z', meaning time zone UTC+0) + * @return OFTrue if certificate expires before the given date, + * or if the given date is invalid; OFFalse otherwise. + */ + OFBool isCertExpiredAt(OFString& date); + + /** returns true if the certificate is expired. + * @return OFTrue if certificate is expired, OFFalse otherwise + */ + OFBool isCertExpiredNow() const; + + /** returns true if the certificate is not yet valid at the given date. + * @param date a string in the format YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ + * (where Z represents the letter 'Z', meaning time zone UTC+0) + * @return OFTrue if certificate is not yet valid at the given date, + * or if the given date is invalid; OFFalse otherwise. + */ + OFBool isCertNotYetValidAt(OFString& date); + + /** returns true if the certificate is not yet valid. + * @return OFTrue if certificate is not yet valid, OFFalse otherwise + */ + OFBool isCertNotYetValidNow() const; + + /** this helper function converts a datetime in ASN1_GENERALIZEDTIME + * format to OFDateTime. + * @param d datetime in ASN1_GENERALIZEDTIME format + * @param dt dt datetime stored in this parameter upon success + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition convertGeneralizedTime(const ASN1_GENERALIZEDTIME *d, OFDateTime& dt); + + /** this helper function converts a datetime in ASN1_TIME format + * (which is in fact an alias for ASN1_STRING) to OFDateTime. + * @param d datetime in ASN1_TIME format + * @param dt dt datetime stored in this parameter upon success + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition convertASN1Time(const ASN1_STRING *d, OFDateTime& dt); + private: /// private undefined copy constructor diff --git a/dcmsign/include/dcmtk/dcmsign/sicertvf.h b/dcmsign/include/dcmtk/dcmsign/sicertvf.h index 3473ae23..59ea7e31 100644 --- a/dcmsign/include/dcmtk/dcmsign/sicertvf.h +++ b/dcmsign/include/dcmtk/dcmsign/sicertvf.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,25 +24,29 @@ #define SICERTVF_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" + class SiCertificate; struct x509_store_st; +struct x509_store_ctx_st; +struct stack_st_X509; // this is STACK_OF(X509) in OpenSSL typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; /** a class representing X.509 public key certificates. * @remark this class is only available if DCMTK is compiled with * OpenSSL support enabled. */ class DCMTK_DCMSIGN_EXPORT SiCertificateVerifier -{ +{ public: /// default constructor SiCertificateVerifier(); - + ///destructor virtual ~SiCertificateVerifier(); @@ -50,8 +54,18 @@ public: * @param fileName path to the certificate file * @param filetype file format: X509_FILETYPE_PEM or X509_FILETYPE_ASN1 * @return SI_EC_Normal if successful, an error code otherwise - */ - OFCondition addTrustedCertificateFile(const char *fileName, int fileType); + */ + virtual OFCondition addTrustedCertificateFile(const char *fileName, int fileType); + + /** loads an untrusted certificate from a file and adds it to the pool + * of untrusted certificates. During certificate verification these will + * only be accepted as intermediate CAs (not as root CA) and will undergo + * additional scrutiny (e.g. check of the purpose extension, if present). + * @param fileName path to the certificate file + * @param filetype file format: X509_FILETYPE_PEM or X509_FILETYPE_ASN1 + * @return SI_EC_Normal if successful, an error code otherwise + */ + virtual OFCondition addUntrustedCertificateFile(const char *fileName, int fileType); /** loads all files as certificates from the specified directory and adds them * to the pool of trusted certificates. @@ -59,15 +73,15 @@ public: * @param filetype file format: X509_FILETYPE_PEM or X509_FILETYPE_ASN1 * @return SI_EC_Normal if successful, an error code otherwise */ - OFCondition addTrustedCertificateDir(const char *pathName, int fileType); + virtual OFCondition addTrustedCertificateDir(const char *pathName, int fileType); - /** loads a certificate revocation list (CRL) in X.509 format from a file and + /** loads a certificate revocation list (CRL) in X.509 format from a file and * adds it to the pool of trusted certificates and CRLs. * @param fileName path to the CRL file * @param filetype file format: X509_FILETYPE_PEM or X509_FILETYPE_ASN1 * @return SI_EC_Normal if successful, an error code otherwise - */ - OFCondition addCertificateRevocationList(const char *fileName, int fileType); + */ + virtual OFCondition addCertificateRevocationList(const char *fileName, int fileType); /** verifies a certificate against the known trusted CA certificates * and certificate revocation lists. Returns a status flag and stores @@ -76,14 +90,49 @@ public: * @return SI_EC_Normal if successful, an error code otherwise. * If the certificate could not be verified, returns SI_EC_VerificationFailed_NoTrust. */ - OFCondition verifyCertificate(SiCertificate& certificate); + virtual OFCondition verifyCertificate(SiCertificate& certificate); /** returns an error string containing a textual description of the result - * of the last call to verifyCertificate() if that call returned + * of the last call to verifyCertificate() if that call returned * SI_EC_VerificationFailed_NoTrust. * @return text string */ - const char *lastError() const; + virtual const char *lastError() const; + + /** returns true if the result of the last call to verifyCertificate() + * was the status code indicating that the certificate has expired, + * false otherwise + * @return true if verifyCertificate() reported certificate expiry. + */ + virtual OFBool lastErrorIsCertExpiry() const; + + /** returns a pointer to the trusted certificate store managed by this object. + * @return pointer to trusted certificate store + */ + virtual X509_STORE *getTrustedCertStore(); + + /** returns a pointer to the stack of untrusted certificates managed by this object. + * Note that the return type is equivalent to OpenSSL's STACK_OF(X509). + * @return pointer to stack of untrusted certificates + */ + virtual stack_st_X509 *getUntrustedCerts(); + + /** enable or disable the verification of certificate revocation lists. + * When enabled, a CRL is expected to be present for every CA certificate, + * and certificate verification will fail if no CRL is found. + * @param enabled OFTrue to enable verification, OFFalse to disable + */ + virtual void setCRLverification(OFBool enabled); + + /** Callback function for certificate verification operations. + * This method can be used by derived classes to examine and modify the + * result of a certificate verification. + * @param deflt default return code that should be returned if the callback does + * not modify the result of the verification + * @param ctx certificate verification context object + * @return result of the verification, 0 for error, 1 for no error, 2 for "policy checking complete". + */ + virtual int verifyCallback(int deflt, X509_STORE_CTX *ctx); private: @@ -94,7 +143,13 @@ private: SiCertificateVerifier& operator=(SiCertificateVerifier& arg); /// OpenSSL X.509 certificate store - X509_STORE* x509store; + X509_STORE *x509store; + + /// OpenSSL X.509 stack of untrusted intermediate certificates + stack_st_X509 *x509untrusted; + + /// flag indicating whether CRL verification should be enabled + OFBool enableCRLverification; /// OpenSSL X.509 certificate verification error code for the last operation long errorCode; @@ -103,3 +158,4 @@ private: #endif #endif + diff --git a/dcmsign/include/dcmtk/dcmsign/sicreapr.h b/dcmsign/include/dcmtk/dcmsign/sicreapr.h index 189b5585..8ab1a592 100644 --- a/dcmsign/include/dcmtk/dcmsign/sicreapr.h +++ b/dcmsign/include/dcmtk/dcmsign/sicreapr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,31 +24,58 @@ #define SICREAPR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sibrsapr.h" /* for SiBaseRSAProfile */ #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sibrsapr.h" /* for SiBaseRSAProfile */ + /** Creator RSA Digital Signature Profile * @remark this class is only available if DCMTK is compiled with * OpenSSL support enabled. */ class DCMTK_DCMSIGN_EXPORT SiCreatorProfile: public SiBaseRSAProfile -{ +{ public: /// default constructor - SiCreatorProfile() { } + SiCreatorProfile(); /// destructor virtual ~SiCreatorProfile() { } - + /** checks whether an attribute with the given tag is required to be signed - * for the current security profile. + * for the current security profile if the attribute is present in the dataset * @param key tag key to be checked * @return true if required, false otherwise. */ - virtual OFBool attributeRequired(const DcmTagKey& key) const; + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; + + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const; + +private: + /// flag indicating whether or not the signature dataset contains the raw data module + OFBool containsRawData_; }; #endif diff --git a/dcmsign/include/dcmtk/dcmsign/sidsa.h b/dcmsign/include/dcmtk/dcmsign/sidsa.h index 02759347..4dc5ac14 100644 --- a/dcmsign/include/dcmtk/dcmsign/sidsa.h +++ b/dcmsign/include/dcmtk/dcmsign/sidsa.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,10 @@ #define SIDSA_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sialgo.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sialgo.h" #include "dcmtk/ofstd/oftypes.h" class SiPrivateKey; diff --git a/dcmsign/include/dcmtk/dcmsign/siecdsa.h b/dcmsign/include/dcmtk/dcmsign/siecdsa.h new file mode 100644 index 00000000..4883cd66 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/siecdsa.h @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 1998-2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiDSA + * + */ + +#ifndef SIECDSA_H +#define SIECDSA_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sialgo.h" +#include "dcmtk/ofstd/oftypes.h" + +class SiPrivateKey; +struct ec_key_st; +typedef struct ec_key_st EC_KEY; + +/** + * This class implements the ECDSA public key crypto algorithms. + * @remark This class is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ + +class DCMTK_DCMSIGN_EXPORT SiECDSA : public SiAlgorithm +{ +public: + + /** constructor + * @param pointer to public ECDSA key + */ + SiECDSA(EC_KEY *key); + + /// destructor + virtual ~SiECDSA(); + + /** creates a signature. + * @param inputHash array of hash key bytes that are to be signed + * @param inputHashSize length of hash key array in bytes + * @param inputHashAlgorithm MAC algorithm used for creation of hash key. Ignored for ECDSA signatures. + * @param outputSignature pointer to array of at least getSize() which must be allocated by caller. + * @param outputSignatureSize returns the number of bytes written to outputSignature. + * @return SI_EC_Normal if successful, errorcode otherwise. + */ + virtual OFCondition sign( + const unsigned char *inputHash, + unsigned long inputHashSize, + E_MACType inputHashAlgorithm, + unsigned char *outputSignature, + unsigned long &outputSignatureSize); + + /** verifies a signature. + * @param inputHash array of bytes containing hash key to be verified against signature + * @param inputHashSize length of hash key array in bytes + * @param inputHashAlgorithm MAC algorithm used for creation of hash key. Ignored for ECDSA signatures. + * @param inputSignature array of bytes containing signature to be verified + * @param inputSignatureSize length of signature array in bytes + * @param verified returns whether the signature was successfully verified + * @return SI_EC_Normal if successful, errorcode otherwise. + */ + virtual OFCondition verify( + const unsigned char *inputHash, + unsigned long inputHashSize, + E_MACType inputHashAlgorithm, + const unsigned char *inputSignature, + unsigned long inputSignatureSize, + OFBool &verified); + + /** returns the size of a block of encrypted/decrypted ciphertext in bytes. + * The result depends on the public key algorithm, key size and padding scheme. + * In general the input to decrypt() or encrypt() must be less than or equal + * to this block size. The output of decrypt() or encrypt() is always equal + * to this block size. + * @return block size for this public key cryptosystem and key + */ + virtual unsigned long getSize() const; + + /** returns the type of public key algorithm computed by this object + * @return type of public key algorithm + */ + virtual E_KeyType keyType() const; + +private: + + /// private undefined copy constructor + SiECDSA(SiECDSA& arg); + + /// private undefined copy assignment operator + SiECDSA& operator=(SiECDSA& arg); + + /// ECDSA key used for signature/verification + EC_KEY *ecdsa; + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/siexit.h b/dcmsign/include/dcmtk/dcmsign/siexit.h new file mode 100644 index 00000000..03f6c662 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/siexit.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (C) 1998-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: exit codes for dcmsign + * + */ + +#ifndef SIEXIT_H +#define SIEXIT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef WITH_OPENSSL + +// exit code constants in addition to those defined in "dcmtk/ofstd/ofexit.h" + +// input file errors (20-39) +#define EXITCODE_CANNOT_READ_TAG_FILE 30 +#define EXITCODE_CANNOT_READ_TSQ_FILE 31 +#define EXITCODE_CANNOT_READ_TSR_FILE 32 +#define EXITCODE_CANNOT_READ_UID_FILE 33 + +// output file errors (40-59) +#define EXITCODE_CANNOT_WRITE_SUPPORT_FILE 46 + +// processing errors (80-99) +#define EXITCODE_CANNOT_ACCESS_SIGNATURE 80 +#define EXITCODE_CANNOT_ACCESS_TS 81 +#define EXITCODE_CANNOT_INSERT_TS 82 +#define EXITCODE_SIGNATURE_REMOVAL_FAILED 83 +#define EXITCODE_SIGNATURE_UID_NOT_FOUND 84 +#define EXITCODE_SIGNATURE_CREATION_FAILED 85 +#define EXITCODE_SYNTAX_ERROR_IN_TAG_FILE 86 +#define EXITCODE_TS_CONSISTENCY_CHECK_FAILED 87 + +// application specific errors (100-119) +#define EXITCODE_NO_SIGNATURES_PRESENT 100 +#define EXITCODE_SIGNATURE_VERIFICATION_FAILED 101 +#define EXITCODE_SIGNATURE_VERIFICATION_POLICY 102 + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/simac.h b/dcmsign/include/dcmtk/dcmsign/simac.h index 4101404c..86faf2cc 100644 --- a/dcmsign/include/dcmtk/dcmsign/simac.h +++ b/dcmsign/include/dcmtk/dcmsign/simac.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,11 @@ #define SIMAC_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" + /** * a base class for all classes that implement hash functions. * @remark this class is only available if DCMTK is compiled with diff --git a/dcmsign/include/dcmtk/dcmsign/simaccon.h b/dcmsign/include/dcmtk/dcmsign/simaccon.h index 035e3e51..fe0eda80 100644 --- a/dcmsign/include/dcmtk/dcmsign/simaccon.h +++ b/dcmsign/include/dcmtk/dcmsign/simaccon.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,10 @@ #define SIMACCON_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" #include "dcmtk/dcmdata/dcostrmb.h" /* for DcmOutputBufferStream */ #include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ #include "dcmtk/dcmdata/dcdeftag.h" @@ -50,14 +50,14 @@ public: /// constructor SiMACConstructor(); - + /// destructor virtual ~SiMACConstructor(); /** encodes a DICOM dataset (or parts of it) as a byte stream in the format * required for DICOM digital signatures and feeds the byte stream into * the given MAC codec. - * If a dump file was set with setDumpFile(), the byte stream is written + * If a dump file was set with setDumpFile(), the byte stream is written * to file as well. * @param item the DICOM dataset to be encoded * @param mac the MAC codec into which the resulting byte stream is fed @@ -69,28 +69,47 @@ public: * attribute tag is contained in this list; the items and elements within the items * are not encoded. * @param tagListIn optional parameter restricting the parts of the dataset - * to be encoded. Only elements which are present in this list of tags, + * to be encoded. Only elements which are present in this list of tags, * which are signable (see DcmTagKey::isSignable()) and are present in the dataset * are encoded. Upon verification of a signature the caller might wish to compare - * tagListIn and tagListOut after successful return to see whether the lists of + * tagListIn and tagListOut after successful return to see whether the lists of * attributes are the same. * If parameter is absent or NULL, a global match is assumed, i.e. all elements * of the dataset which are present and signable are encoded. * @return status code */ OFCondition encodeDataset( - DcmItem& item, - SiMAC& mac, + DcmItem& item, + SiMAC& mac, E_TransferSyntax oxfer, DcmAttributeTag &tagListOut, DcmAttributeTag *tagListIn = NULL); + /** encodes a DICOM dataset (or parts of it) as a byte stream in the format + * required for DICOM digital signatures and feeds the byte stream into + * the given MAC codec, for the purpose of signature verification + * If a dump file was set with setDumpFile(), the byte stream is written + * to file as well. + * @param item the DICOM dataset to be encoded + * @param mac the MAC codec into which the resulting byte stream is fed + * @param oxfer the transfer syntax to be used when encoding the dataset. + * The caller might wish to use DcmItem::canWriteXfer() to check beforehand + * whether this transfer syntax can be used. + * @param tagListIn list of elements to be encoded. + * @return status code + */ + OFCondition encodeDatasetForVerification( + DcmItem& item, + SiMAC& mac, + E_TransferSyntax oxfer, + DcmAttributeTag *tagListIn); + /** encodes the contents of the digital signature sequence * except CertificateOfSigner, Signature, CertifiedTimestampType * and CertifiedTimestamp as a byte stream in the format * required for DICOM digital signatures and feeds the byte stream into * the given MAC codec. - * If a dump file was set with setDumpFile(), the byte stream is written + * If a dump file was set with setDumpFile(), the byte stream is written * to file as well. * @param signatureItem the DICOM digital signature item to be encoded * @param mac the MAC codec into which the resulting byte stream is fed @@ -100,8 +119,8 @@ public: * @return status code */ OFCondition encodeDigitalSignatureItem( - DcmItem& signatureItem, - SiMAC& mac, + DcmItem& signatureItem, + SiMAC& mac, E_TransferSyntax oxfer); /** flushes all buffers inside this object, finalizing the MAC code @@ -130,8 +149,8 @@ private: */ OFCondition flushBuffer(SiMAC& mac); - /** feeds a DcmElement into the MAC data stream if is signable. - * If the element is a sequence, all signable elements from all items are added. + /** feeds a DcmElement into the MAC data stream if is signable. + * If the element is a sequence, all signable elements from all items are added. * @param element pointer to element, must not be NULL * @param mac MAC to use * @param oxfer transfer syntax in which data is encoded @@ -154,7 +173,7 @@ private: /// the internal buffer stream DcmOutputBufferStream stream; - + /** if nonzero, the data fed to the MAC algorithm * is also stored in this file. */ diff --git a/dcmsign/include/dcmtk/dcmsign/simd5.h b/dcmsign/include/dcmtk/dcmsign/simd5.h index 06048e5d..1ccaa437 100644 --- a/dcmsign/include/dcmtk/dcmsign/simd5.h +++ b/dcmsign/include/dcmtk/dcmsign/simd5.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,11 +24,12 @@ #define SIMD5_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/simac.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/simac.h" +#include "dcmtk/dcmsign/sitypes.h" + struct MD5state_st; typedef struct MD5state_st MD5_CTX; diff --git a/dcmsign/include/dcmtk/dcmsign/sinullpr.h b/dcmsign/include/dcmtk/dcmsign/sinullpr.h index 6a711490..c09d5053 100644 --- a/dcmsign/include/dcmtk/dcmsign/sinullpr.h +++ b/dcmsign/include/dcmtk/dcmsign/sinullpr.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,11 +24,12 @@ #define SINULLPR_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sisprof.h" /* for SiSecurityProfile */ #ifdef WITH_OPENSSL -/** defines a "null" security profile that does not require or forbid any +#include "dcmtk/dcmsign/sisprof.h" /* for SiSecurityProfile */ + +/** defines a "null" security profile that does not require or forbid any * MAC algorithm, signature algorithm, or attribute tag. This class can be * used to clean up a proposed attribute list against a dataset. * @remark this class is only available if DCMTK is compiled with @@ -43,7 +44,7 @@ public: /// destructor virtual ~SiNullProfile() { } - + /** checks whether the given MAC type can be used with this security profile. * @param macType MAC type to be checked * @return true if MAC type is allowable for this profile, false otherwise. @@ -63,11 +64,18 @@ public: virtual OFBool isAllowableTransferSyntax(E_TransferSyntax xfer) const; /** checks whether an attribute with the given tag is required to be signed - * for the current security profile. + * for the current security profile if the attribute is present in the dataset * @param key tag key to be checked * @return true if required, false otherwise. */ - virtual OFBool attributeRequired(const DcmTagKey& key) const; + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; /** checks whether an attribute with the given tag must not be signed * for the current security profile. @@ -76,6 +84,21 @@ public: */ virtual OFBool attributeForbidden(const DcmTagKey& key) const; + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const; + }; #endif diff --git a/dcmsign/include/dcmtk/dcmsign/siprivat.h b/dcmsign/include/dcmtk/dcmsign/siprivat.h index ad96a449..90458af6 100644 --- a/dcmsign/include/dcmtk/dcmsign/siprivat.h +++ b/dcmsign/include/dcmtk/dcmsign/siprivat.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,10 @@ #define SIPRIVAT_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" #include "dcmtk/ofstd/ofstring.h" class SiAlgorithm; diff --git a/dcmsign/include/dcmtk/dcmsign/sipurpos.h b/dcmsign/include/dcmtk/dcmsign/sipurpos.h new file mode 100644 index 00000000..8c4e9638 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/sipurpos.h @@ -0,0 +1,156 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiSignaturePurpose + * + */ + +#ifndef SIPURPOS_H +#define SIPURPOS_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sidefine.h" +#include "dcmtk/ofstd/ofstream.h" + +class DcmItem; +class OFCondition; + +/** Helper class for the Digital Signature Purpose Code Sequence. + * @remark this class is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +class DCMTK_DCMSIGN_EXPORT SiSignaturePurpose +{ +public: + + /** purpose of digital signature as defined in DICOM BCID 7007. + * @remark this enum is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ + enum E_SignaturePurposeType + { + /// no signature purpose specified + ESP_none = 0, + + /// Author's Signature + ESP_AuthorsSignature = 1, + + /// Coauthor's Signature + ESP_CoauthorsSignature = 2, + + /// Co-participant's Signature + ESP_CoparticipantsSignature = 3, + + /// Transcriptionist/Recorder Signature + ESP_TranscriptionistSignature = 4, + + /// Verification Signature + ESP_VerificationSignature = 5, + + /// Validation Signature + ESP_ValidationSignature = 6, + + /// Consent Signature + ESP_ConsentSignature = 7, + + /// Signature Witness Signature + ESP_SignatureWitnessSignature = 8, + + /// Event Witness Signature + ESP_EventWitnessSignature = 9, + + /// Identity Witness Signature + ESP_IdentityWitnessSignature = 10, + + /// Consent Witness Signature + ESP_ConsentWitnessSignature = 11, + + /// Interpreter Signature + ESP_InterpreterSignature = 12, + + /// Review Signature + ESP_ReviewSignature = 13, + + /// Source Signature + ESP_SourceSignature = 14, + + /// Addendum Signature + ESP_AddendumSignature = 15, + + /// Modification Signature + ESP_ModificationSignature = 16, + + /// Administrative (Error/Edit) Signature + ESP_AdministrativeSignature = 17, + + /// Timestamp Signature + ESP_TimestampSignature = 18 + + }; + + /** return the code value for the given signature purpose + * @return code value for the given signature purpose, NULL for ESP_none + */ + static const char *getCodeValue(E_SignaturePurposeType purpose); + + /** return the code meaning for the given signature purpose + * @return code meaning for the given signature purpose, NULL for ESP_none + */ + static const char *getCodeMeaning(E_SignaturePurposeType purpose); + + /** return the coding scheme designator for the given signature purpose + * @return coding scheme designator for the given signature purpose + */ + static const char *getCodingSchemeDesignator(E_SignaturePurposeType purpose); + + /** insert a digital signature purpose code sequence into the given DICOM item + * @param seqItem item into which the sequence is inserted. This should be an item + * of the DigitalSignaturesSequence. + * @param sigPurpose signature purpose. If the purpose is ESP_none, nothing will be + * inserted and this method will immediately return with EC_Normal + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition insertDigitalSignaturePurposeCodeSQ(DcmItem& seqItem, E_SignaturePurposeType sigPurpose); + + /** determine the signature purpose to be used, and prints a warning to the logger if + * an override required by the signature profile causes the user selection to be ignored. + * @param currentPurpose signature purpose selected by the user + * @param overridePurpose override signature purpose required by the signature profile + * @return signature purpose to be used for the digital signature purpose code sequence + */ + static E_SignaturePurposeType determineOverridePurpose(E_SignaturePurposeType currentPurpose, E_SignaturePurposeType overridePurpose); + + /** look-up signature purpose enum by number + * @param num number, 0 for ESP_none, 1 for ESP_AuthorsSignature etc. + * @return signature purpose enum or ESP_none if number too high. + */ + static E_SignaturePurposeType lookup(size_t num); + + /** print a list of all signature purpose codes supported by this helper class. + * This is used by dcmsign --list-purposes. + * @param out output stream to print to + */ + static void printSignatureCodes(STD_NAMESPACE ostream& out); + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/siripemd.h b/dcmsign/include/dcmtk/dcmsign/siripemd.h index 2cfadba4..3381bda9 100644 --- a/dcmsign/include/dcmtk/dcmsign/siripemd.h +++ b/dcmsign/include/dcmtk/dcmsign/siripemd.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,11 +24,12 @@ #define SIRIPEMD_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/simac.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/simac.h" +#include "dcmtk/dcmsign/sitypes.h" + struct RIPEMD160state_st; typedef struct RIPEMD160state_st RIPEMD160_CTX; diff --git a/dcmsign/include/dcmtk/dcmsign/sirsa.h b/dcmsign/include/dcmtk/dcmsign/sirsa.h index d71a5c09..7e089589 100644 --- a/dcmsign/include/dcmtk/dcmsign/sirsa.h +++ b/dcmsign/include/dcmtk/dcmsign/sirsa.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,10 +24,10 @@ #define SIRSA_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sialgo.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sialgo.h" #include "dcmtk/ofstd/oftypes.h" class SiPrivateKey; diff --git a/dcmsign/include/dcmtk/dcmsign/sisha1.h b/dcmsign/include/dcmtk/dcmsign/sisha1.h index 98b78a3d..db58e2f2 100644 --- a/dcmsign/include/dcmtk/dcmsign/sisha1.h +++ b/dcmsign/include/dcmtk/dcmsign/sisha1.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,11 +24,12 @@ #define SISHA1_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/simac.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/simac.h" +#include "dcmtk/dcmsign/sitypes.h" + struct SHAstate_st; typedef struct SHAstate_st SHA_CTX; diff --git a/dcmsign/include/dcmtk/dcmsign/sisprof.h b/dcmsign/include/dcmtk/dcmsign/sisprof.h index e81aad05..69d1e54d 100644 --- a/dcmsign/include/dcmtk/dcmsign/sisprof.h +++ b/dcmsign/include/dcmtk/dcmsign/sisprof.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,11 +24,12 @@ #define SISPROF_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" /* for E_KeyType */ #ifdef WITH_OPENSSL -#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ +#include "dcmtk/dcmsign/sitypes.h" /* for E_KeyType */ +#include "dcmtk/dcmsign/sipurpos.h" /* for E_SignaturePurposeType */ +#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ class SiAlgorithm; class DcmItem; @@ -49,7 +50,7 @@ public: /// destructor virtual ~SiSecurityProfile() { } - + /** checks whether the given MAC type can be used with this security profile. * @param macType MAC type to be checked * @return true if MAC type is allowable for this profile, false otherwise. @@ -67,7 +68,7 @@ public: * @return true if public key algorithm is allowable for this profile, false otherwise. */ virtual OFBool isAllowableAlgorithmType(E_KeyType keyType) const = 0; - + /** checks whether the given public/private key object can be used with this security profile. * @param algo object to be checked * @return true if object is allowable for this profile, false otherwise. @@ -79,13 +80,13 @@ public: * @return true if transfer syntax is allowable for this profile, false otherwise. */ virtual OFBool isAllowableTransferSyntax(E_TransferSyntax xfer) const = 0; - + /** checks whether an attribute with the given tag is required to be signed - * for the current security profile. + * for the current security profile if the attribute is present in the dataset * @param key tag key to be checked * @return true if required, false otherwise. */ - virtual OFBool attributeRequired(const DcmTagKey& key) const = 0; + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const = 0; /** checks whether an attribute with the given tag must not be signed * for the current security profile. @@ -93,7 +94,7 @@ public: * @return true if attribute must not be signed, false otherwise. */ virtual OFBool attributeForbidden(const DcmTagKey& key) const = 0; - + /** updates the given list of attribute tags according to the * requirements of the current security profile. For all elements present in the * dataset, the attribute tag is inserted or removed from the list if required by the profile. @@ -103,14 +104,50 @@ public: */ virtual OFCondition updateAttributeList(DcmItem &item, DcmAttributeTag& tagList); + /** create a maximum list of attribute tags according to the + * requirements of the current security profile. For all elements present in the + * dataset, the attribute tag is inserted if permitted by the profile. + * @param item dataset to be handled + * @param tagList attribute tag list to be created + * @return status code + */ + virtual OFCondition createAttributeList(DcmItem &item, DcmAttributeTag& tagList); + /** checks whether the given list of attribute tags fulfils the requirements - * of the current security profile for the given dataset. + * of the current security profile for the given dataset. * @param item dataset to be checked - * @param tagList attribute tag list. + * @param tagList attribute tag list. * @return true if minimum requirements for profile are fulfilled, false otherwise. - */ + */ virtual OFBool checkAttributeList(DcmItem &item, DcmAttributeTag& tagList); + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const = 0; + + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item) = 0; + + /** return the required digital signature purpose for this signature profile + * @return required signature purpose if any, ESP_none otherwise + */ + virtual SiSignaturePurpose::E_SignaturePurposeType getOverrideSignaturePurpose() const; + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const = 0; + /** checks if the given tag key is contained in the given list. * @param tagList list of tag keys * @param key tag key diff --git a/dcmsign/include/dcmtk/dcmsign/sisrpr.h b/dcmsign/include/dcmtk/dcmsign/sisrpr.h new file mode 100644 index 00000000..bd670532 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/sisrpr.h @@ -0,0 +1,77 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiStructuredReportingProfile + * + */ + +#ifndef SISRPR_H +#define SISRPR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmsign/sibrsapr.h" /* for SiBaseRSAProfile */ + +#ifdef WITH_OPENSSL + +/** Structured Reporting RSA Digital Signature Profile + * @remark this class is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +class DCMTK_DCMSIGN_EXPORT SiStructuredReportingProfile: public SiBaseRSAProfile +{ +public: + + /// default constructor + SiStructuredReportingProfile() { } + + /// destructor + virtual ~SiStructuredReportingProfile() { } + + /** checks whether an attribute with the given tag is required to be signed + * for the current security profile if the attribute is present in the dataset + * @param key tag key to be checked + * @return true if required, false otherwise. + */ + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; + + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** returns true if this signature profile only applies to main dataset level + * @return OFTrue if this signature profile only applies to main dataset level, OFFalse otherwise + */ + virtual OFBool mainDatasetRequired() const; + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/sisrvpr.h b/dcmsign/include/dcmtk/dcmsign/sisrvpr.h new file mode 100644 index 00000000..af6fc575 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/sisrvpr.h @@ -0,0 +1,78 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiStructuredReportingVerificationProfile + * + */ + +#ifndef SISRVPR_H +#define SISRVPR_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sisrpr.h" /* for SiStructuredReportingProfile */ + +/** Structured Reporting RSA Digital Signature Profile - Verification Signature + * @remark this class is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +class DCMTK_DCMSIGN_EXPORT SiStructuredReportingVerificationProfile: public SiStructuredReportingProfile +{ +public: + + /// default constructor + SiStructuredReportingVerificationProfile() { } + + /// destructor + virtual ~SiStructuredReportingVerificationProfile() { } + + /** checks whether an attribute with the given tag is required to be signed + * for the current security profile if the attribute is present in the dataset + * @param key tag key to be checked + * @return true if required, false otherwise. + */ + virtual OFBool attributeRequiredIfPresent(const DcmTagKey& key) const; + + /** checks whether all attributes that are required unconditionally + * to be signed in this profile are included in the given tagList. + * @param taglist attribute tag list + * @return true if requirements for profile are fulfilled, false otherwise. + */ + virtual OFBool checkRequiredAttributeList(DcmAttributeTag& tagList) const; + + /** some digital signature profiles specify conditions under which certain + * attributes must be included into the signature. + * This method allows the signature profile to inspect the dataset in order + * to determine whether or not the conditions are met. + * This method should be called before DcmSignature::createSignature() is executed. + * @param item the dataset or item to which the signature will be added + * @return status code + */ + virtual OFCondition inspectSignatureDataset(DcmItem &item); + + /** return the required digital signature purpose for this signature profile + * @return for this class, this method always returns ESP_VerificationSignature. + */ + virtual SiSignaturePurpose::E_SignaturePurposeType getOverrideSignaturePurpose() const; + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/sitsfs.h b/dcmsign/include/dcmtk/dcmsign/sitsfs.h new file mode 100644 index 00000000..91bb67c8 --- /dev/null +++ b/dcmsign/include/dcmtk/dcmsign/sitsfs.h @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 1998-2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiTimeStampFS + * + */ + +#ifndef SITSFS_H +#define SITSFS_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sitstamp.h" /* for class SiTimeStamp */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ + +/** timestamp client based on filesystem interactions. + * This timestamp client will write a timestamp query in DES encoding to file. + * The interaction with the time stamp authority must then take place separately + * (e.g. manually, using a command line tool like curl). This client then offers + * functionality to import a timestamp reponse (i.e. a timestamp) from file + * and place it into the signed DICOM file for which the timestamp was requested. + * @remark this class is only available if DCMTK is compiled with OpenSSL support enabled. + */ +class DCMTK_DCMSIGN_EXPORT SiTimeStampFS : public SiTimeStamp +{ +public: + + /// default constructor + SiTimeStampFS(); + + /// destructor + virtual ~SiTimeStampFS(); + + /** takes a block of raw data, creates a time stamp query for a hash of this + * raw data, and stores it locally in this object. + * @param inputData pointer to raw data + * @param inputDataSize length of raw data block in bytes + * @return status code + */ + virtual OFCondition stamp( + const unsigned char *inputData, + unsigned long inputDataSize); + + /** writes the time stamp query created with SiTimeStampFS::stamp() to a file. + * Also writes a "UID file" that contains the Digital Signature UID of the signature + * to which the timestamp request belongs. This file will be read later by the + * import function. The filenames of timestamp query file and UID file must be + * set prior to calling this method. + * @param item item of the DigitalSignatureSQ to which the timestamp is written + * @return dcmdata OFCondition status code + */ + virtual OFCondition write(DcmItem& item); + + /** set the time stamp query filename to be written + * @param fname filename + */ + virtual void setTSQFilename(const char *fname); + + /** set the time stamp response filename to be read + * @param fname filename + */ + virtual void setTSRFilename(const char *fname); + + /** set the uid file filename to be written + * @param fname filename + */ + virtual void setUIDFilename(const char *fname); + + /** load UID file and retrieve digital signature UID + * @param uid digital signature returned in this parameter if successful + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition getUIDFromFile(OFString& uid); + + /** load timestamp query from file + * @return status code + */ + virtual OFCondition load_ts_query_from_file(); + + /** load timestamp response from file + * @return status code + */ + virtual OFCondition load_ts_response_from_file(); + + /** check consistency between timestamp query (if available), timestamp + * response and DICOM digital signature. Query and response files must have + * been loaded prior to this method call. + * @param ditem item of the DigitalSignaturesSequence to which this timestamp belongs + * @return status code + */ + virtual OFCondition check_ts_response(DcmItem& ditem); + + /** insert timestamp token into DICOM dataset + * The response file must have been loaded and checked prior to this method call. + * @param ditem item of the DigitalSignaturesSequence to which this timestamp is written + * @return status code + */ + virtual OFCondition write_ts_token(DcmItem& ditem); + +private: + + /// filename of the timestamp query file to be written + OFString tsqFilename_; + + /// filename of the timestamp response file to be read + OFString tsrFilename_; + + /// filename of the UID file to be written + OFString uidFilename_; + +}; + +#endif +#endif diff --git a/dcmsign/include/dcmtk/dcmsign/sitstamp.h b/dcmsign/include/dcmtk/dcmsign/sitstamp.h index de144dd4..9e329dc5 100644 --- a/dcmsign/include/dcmtk/dcmsign/sitstamp.h +++ b/dcmsign/include/dcmtk/dcmsign/sitstamp.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -24,27 +24,40 @@ #define SITSTAMP_H #include "dcmtk/config/osconfig.h" -#include "dcmtk/dcmsign/sitypes.h" #ifdef WITH_OPENSSL +#include "dcmtk/dcmsign/sitypes.h" +#include "dcmtk/ofstd/ofstring.h" + +// forward declarations class DcmItem; - -/** pure virtual base class for a timestamp client. +class SiCertificateVerifier; +class SiCertificate; +struct TS_req_st; +struct TS_resp_st; +struct TS_tst_info_st; +typedef struct TS_req_st TS_REQ; +typedef struct TS_resp_st TS_RESP; +typedef struct TS_tst_info_st TS_TST_INFO; +typedef struct pkcs7_st PKCS7; + +/** Base class for a timestamp client. * Instances of derived classes are able to request timestamps from a timestamp service. - * Timestamps are not supported (yet). - * @remark this class is only available if DCMTK is compiled with - * OpenSSL support enabled. + * This class implements the code needed to create a timestamp request and to insert + * a timestamp reply into a DICOM dataset, but not the protocol for actually + * interacting with a timestamp authority. + * @remark this class is only available if DCMTK is compiled with OpenSSL support enabled. */ class DCMTK_DCMSIGN_EXPORT SiTimeStamp -{ +{ public: /// default constructor - SiTimeStamp() { } - + SiTimeStamp(); + /// destructor - virtual ~SiTimeStamp() { } + virtual ~SiTimeStamp(); /** takes a block of raw data and requests a time stamp for this raw data. * @param inputData pointer to raw data @@ -52,16 +65,248 @@ public: * @return status code */ virtual OFCondition stamp( - const unsigned char *inputData, + const unsigned char *inputData, unsigned long inputDataSize) = 0; + /** reads the current timestamp from an item of the Digital Signatures Sequence + * and creates a timestamp ticket object. + * @param item item of the DigitalSignatureSQ from which the timestamp is read + * @return status code + */ + virtual OFCondition read(DcmItem& item); + /** writes the current timestamp into an item of the Digital Signatures Sequence * and creates the timestamp type information in the item. * @param item item of the DigitalSignatureSQ to which the timestamp is written - * @return dcmdata OFCondition status code + * @return status code */ virtual OFCondition write(DcmItem& item) = 0; + /** set the requested policy OID to be included into the time stamp query + * @param oid policy OID, NULL for no policy (which is the default). + */ + virtual void setPolicyOID(const char *oid); + + /** sets the flag controlling whether or not a nonce is included + * into the timestamp query. Since a nonce is a protection against replay + * attack, normally it should be included, and this is also the default. + * @param nonce OFTrue if nonce should be included, OFFalse otherwise + */ + virtual void setNonce(OFBool nonce); + + /** sets the flag controlling whether the timestamp authority will be + * requested to include its certificate into the timestamp reply. + * A timestamp reply with certificate is easier to verify, as less + * external key material is required, but somewhat larger. + * Default is OFTrue; + * @param creq OFTrue if certificate should be requested, OFFalse otherwise + */ + virtual void setCertificateRequested(OFBool creq); + + /** sets the message authentication code to be used for creating + * the hash value in the timestamp query. Default is SHA256. + * @param creq OFTrue if certificate should be requested, OFFalse otherwise + */ + virtual void setMAC(E_MACType mac); + + // methods that return the various attributes of a timestamp ticket + + /** checks if this object contains a timestamp ticket info object + * @return OFTrue if timestamp ticket info available, OFFalse otherwise + */ + virtual OFBool have_tsinfo() const; + + /** returns the timestamp ticket info version number + * @return tsinfo version number if available, -1 otherwise + */ + virtual long get_tsinfo_version() const; + + /** returns the timestamp ticket info policy OID + * @param oid upon return, contains the policy OID if available, an empty string otherwise + */ + virtual void get_tsinfo_policy_oid(OFString& oid) const; + + /** returns the timestamp ticket info MAC algorithm name + * @param mac upon return, contains the MAC algorithm name if available, an empty string otherwise + */ + virtual void get_tsinfo_imprint_algorithm_name(OFString& mac) const; + + /** returns the timestamp ticket info serial number + * @param serial upon return, contains the serial number if available, an empty string otherwise + */ + virtual void get_tsinfo_serial_number(OFString& serial) const; + + /** returns the timestamp ticket info nonce, if present + * @param nonce upon return, contains the nonce if available, an empty string otherwise + */ + virtual void get_tsinfo_nonce(OFString& nonce) const; + + /** returns the timestamp ticket info timestamp authority (TSA) name, if present + * @param tsa upon return, contains the TSA name if available, an empty string otherwise + */ + virtual void get_tsinfo_tsa_name(OFString& tsa) const; + + /** returns the timestamp ticket info ordering flag + * @return OFTrue if timestamp ticket is present and contains an ordering flag with value "true", OFFalse otherwise + */ + virtual OFBool get_tsinfo_ordering() const; + + /** returns the timestamp ticket info accuracy, if present + * @param accuracy upon return, contains the accuracy if available, an empty string otherwise + */ + virtual void get_tsinfo_accuracy(OFString& accuracy) const; + + /** returns the timestamp date/time information, if present + * @param ts upon return, contains the timestamp date/time information, an empty string otherwise + */ + virtual void get_tsinfo_timestamp(OFString& ts) const; + + /** returns the number of extensions in the timestamp ticket + * @return number of extensions in the timestamp ticket + */ + virtual int get_tsinfo_numextensions() const; + + /** returns one timestamp extension, if present + * @param ext upon return, contains the timestamp extension if present, an empty string otherwise + * @param idx number of the extension, 0 <= idx < get_tsinfo_numextensions(). + */ + virtual void get_tsinfo_extension(OFString& ext, int idx) const; + + /** this method performs the following functions: + * - it checks if there is one and only one signer. + * - it identifies the signer certificate (which may be embedded in the timestamp, or loaded in the SiCertificateVerifier store) + * - it checks the extended key usage and key usage fields of the signer certificate + * - it verifies the certificate path + * - it checks if the certificate path meets the requirements of the + * SigningCertificate ESS signed attribute. + * - it verifies the signature value (against the imprint in the timestamp token + * - it prints the contents of the signer certificate to the logger + * @param cv container for the certificates used during verification + * @return EC_Normal upon success, an error code otherwise. + */ + virtual OFCondition verifyTSSignature(SiCertificateVerifier& cv); + + /** Verify the timestamp token by checking that its imprint is + * indeed a hash of the DICOM signature, that the version number + * is as expected and that the TSA name, if provided in the timestamp + * ticket structure, matches the name of the TSA given in the TSA + * certificate. + * @param cv container for the certificates used during verification + * @param ditem item of the Digital Signatures Sequence containing the timestamp + * @param cert certificate of the signer of the DICOM signature, used to check + * the date/time of the timestamp against the validity period of the certificate + * @return EC_Normal upon success, an error code otherwise. + */ + virtual OFCondition verifyTSToken( + SiCertificateVerifier& cv, + DcmItem& ditem, + SiCertificate& cert); + + /** returns an error string containing a textual description of the result + * of the last call to verifyTSSignature() or verifyTSToken() + * if that call returned SI_EC_TimestampSignatureVerificationFailed. + * @param err text string returned in this parameter + */ + void lastError(OFString& err) const; + +protected: + + /** takes a block of raw data, computes a message digest and creates + * a time stamp query object. + * @param inputData pointer to raw data + * @param inputDataSize length of raw data block in bytes + * @return status code + */ + virtual OFCondition create_ts_query( + const unsigned char *inputData, + unsigned long inputDataSize); + + /** return pointer to timestamp query object, may be NULL. + * @return pointer to timestamp query object, may be NULL. + */ + virtual TS_REQ *getTSQ() { return tsq_; } + + /** return pointer to timestamp response object, may be NULL. + * @return pointer to timestamp response object, may be NULL. + */ + virtual TS_RESP *getTSR() { return tsr_; } + + /** return pointer to timestamp ticket object, may be NULL. + * @return pointer to timestamp ticket object, may be NULL. + */ + virtual PKCS7 *getTS() { return ts_; } + + /** return pointer to timestamp ticket info object, may be NULL. + * @return pointer to timestamp ticket info object, may be NULL. + */ + virtual TS_TST_INFO *getTSInfo() { return tsinfo_; } + + /** load timestamp query from file + * @param fname filename, must not be NULL + * @return status code + */ + virtual OFCondition load_ts_query(const char *fname); + + /** load timestamp response from file + * @param fname filename, must not be NULL + * @return status code + */ + virtual OFCondition load_ts_response(const char *fname); + + /** check consistency between timestamp query (if available), timestamp + * response and DICOM digital signature. + * @param tsq pointer to timestamp query, may be NULL + * @param tsr pointer to timestamp response, must not be NULL + * @param ditem item of the DigitalSignaturesSequence to which this timestamp belongs + * @return status code + */ + static OFCondition check_ts_response( + TS_REQ *tsq, + TS_RESP *tsr, + DcmItem& ditem); + + /** insert timestamp token into DICOM dataset + * The timestamp response must have been checked prior to this method call. + * @param tsr pointer to timestamp response, must not be NULL + * @param ditem item of the DigitalSignaturesSequence to which this timestamp is written + * @return status code + */ + static OFCondition write_ts_token( + TS_RESP *tsr, + DcmItem& ditem); + +private: + + /// time stamping policy OID to be included in the time stamp query. Default is empty. + OFString tsq_policy_; + + /// MAC algorithm for creating the hash key to be timestamped. Default is SHA-256. + E_MACType tsq_mac_; + + /// Use a pseudo-random nonce in the time stamp query. Default is OFTrue. + OFBool tsq_use_nonce_; + + /// Request the TSA certificate to be embedded into the time stamp reply. Default is OFTrue. + OFBool tsq_certificate_requested_; + + /// pointer to time stamp request object, may be NULL + TS_REQ *tsq_; + + /// pointer to time stamp response object, may be NULL + TS_RESP *tsr_; + + /// pointer to time stamp ticket object, may be NULL + PKCS7 *ts_; + + /// pointer to time stamp ticket info object (extracted from the timestamp ticket), may be NULL + TS_TST_INFO *tsinfo_; + + /// OpenSSL X.509 certificate verification error code for the last operation + long errorCode_; + + /// error string for the last operation, valid if errorCode_ < 0 + const char *errorString_; + }; #endif diff --git a/dcmsign/include/dcmtk/dcmsign/sitypes.h b/dcmsign/include/dcmtk/dcmsign/sitypes.h index bb99401d..03c57efe 100644 --- a/dcmsign/include/dcmtk/dcmsign/sitypes.h +++ b/dcmsign/include/dcmtk/dcmsign/sitypes.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -31,19 +31,20 @@ #include "dcmtk/ofstd/ofcond.h" #include "dcmtk/oflog/oflog.h" #include "dcmtk/dcmsign/sidefine.h" +#include "dcmtk/dcmsign/sitypes.h" /* ** Logging */ -extern DCMTK_DCMSIGN_EXPORT OFLogger DCM_dcmsignLogger; +extern DCMTK_DCMSIGN_EXPORT OFLogger dcmsignLogger; -#define DCMSIGN_TRACE(msg) OFLOG_TRACE(DCM_dcmsignLogger, msg) -#define DCMSIGN_DEBUG(msg) OFLOG_DEBUG(DCM_dcmsignLogger, msg) -#define DCMSIGN_INFO(msg) OFLOG_INFO(DCM_dcmsignLogger, msg) -#define DCMSIGN_WARN(msg) OFLOG_WARN(DCM_dcmsignLogger, msg) -#define DCMSIGN_ERROR(msg) OFLOG_ERROR(DCM_dcmsignLogger, msg) -#define DCMSIGN_FATAL(msg) OFLOG_FATAL(DCM_dcmsignLogger, msg) +#define DCMSIGN_TRACE(msg) OFLOG_TRACE(dcmsignLogger, msg) +#define DCMSIGN_DEBUG(msg) OFLOG_DEBUG(dcmsignLogger, msg) +#define DCMSIGN_INFO(msg) OFLOG_INFO(dcmsignLogger, msg) +#define DCMSIGN_WARN(msg) OFLOG_WARN(dcmsignLogger, msg) +#define DCMSIGN_ERROR(msg) OFLOG_ERROR(dcmsignLogger, msg) +#define DCMSIGN_FATAL(msg) OFLOG_FATAL(dcmsignLogger, msg) // DICOM defined terms for MAC algorithms, certificate and timestamp types @@ -56,7 +57,6 @@ extern DCMTK_DCMSIGN_EXPORT OFLogger DCM_dcmsignLogger; #define SI_DEFTERMS_SHA384 "SHA384" #define SI_DEFTERMS_SHA512 "SHA512" - // include this file in doxygen documentation /** @file sitypes.h @@ -79,6 +79,9 @@ enum E_KeyType /// DH key EKT_DH, + /// EC key + EKT_EC, + /// no key present EKT_none }; @@ -109,84 +112,185 @@ enum E_MACType EMT_SHA512 }; +/** signature verification policy + * @remark this enum is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +enum E_SignatureVerificationPolicy +{ + /// verify signatures if present, pass otherwise + ESVP_verifyIfPresent, + + /// fail if no signature is present at all but do not check any signature profile + ESVP_requireSignature, + + /// fail if no valid creator RSA signature is present on the main dataset level + ESVP_requireCreatorRSASignature, + + /// fail if no valid authorization RSA signature is present on the main dataset level + ESVP_requireAuthorizationRSASignature, + + /// fail if no valid SR RSA signature is present on the main dataset level + ESVP_requireSRRSASignature +}; + +/** verification policy for certified timestamps attached to signatures + * @remark this enum is only available if DCMTK is compiled with + * OpenSSL support enabled. + */ +enum E_TimestampVerificationPolicy +{ + /// verify timestamp if present, pass otherwise + ETVP_verifyTSIfPresent, + + /// ignore certified timestamp even if present + ETVP_ignoreTS, + + /// fail if signature does not contain a certified timestamp + ETVP_requireTS, + +}; + + /* * specific error conditions for module dcmsign */ /// object initialization failed -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_InitializationFailed; /// an OpenSSL call has failed -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_OpenSSLFailure; /// file cannot be read -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_CannotRead; /// unable to use the selected transfer syntax for MAC computation -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_WrongTransferSyntax; /// no more MAC ID numbers available -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_MacIDsExhausted; /// certificate and private key do not match -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_CertificateDoesNotMatchPrivateKey; /// MAC algorithm not allowed for the current security profile -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_MacDoesNotMatchProfile; /// Signature algorithm not allowed for the current security profile -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_AlgorithmDoesNotMatchProfile; /// Transfer syntax not allowed for the current security profile -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_TransferSyntaxDoesNotMatchProfile; -/** signature verification failed because the certificate is missing - * or cannot be read (e.g. unsupported format) - * @remark this constant is only available if DCMTK is compiled with - * OpenSSL support enabled. - */ +/// Dataset is not suitable for the current security profile (e.g. wrong SOP class) +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_DatasetDoesNotMatchProfile; + +/// signature verification failed because the certificate is missing or cannot be read (e.g. unsupported format) +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_NoCertificate; /// signature verification failed because the corresponding MAC parameters item could not be found or is incomplete -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_NoMAC; /// signature verification failed because the corresponding signature item is incomplete -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_NoSignature; /// signature verification failed because the MAC algorithm is not supported -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_UnsupportedMACAlgorithm; /// signature verification failed because the signature is invalid (document corrupted) +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_Corrupted; /// signature verification failed because the certificate was issued by an untrusted (unknown) CA -/// @remark this constant is only available if DCMTK is compiled with -/// OpenSSL support enabled. +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_NoTrust; +/// unsupported MAC algorithm specified +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_UnsupportedMAC; + +/// invalid object identifier (OID) string +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_InvalidOID; + +/// unable to write time stamp query file +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_CannotWriteTSQ; + +/// verification of timestamp response message failed +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_InvalidTSR; + +/// signature verification failed because DataElementsSigned is missing or incorrect +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_NoDataElementsSigned; + +/// List of data elements signed does not match the profile requirements +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_DataElementsSignedDoesNotMatchProfile; + +/// desired signature location item not found +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_ItemLocationNotFound; + +/// unknown certified timestamp type +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_UnknownTimestampType; + +/// certified timestamp in dataset cannot be read +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_InvalidTimestamp; + +/// filetype is unknown (neither PEM nor DER) +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_InvalidFiletype; + +/// signature verification of the certified timestamp failed +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_TimestampSignatureVerificationFailed; + +/// signature verification failed because the certificate was already expired at the signature create date +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_CertExpiredAtSignature; + +/// signature verification failed because the certificate was not yet valid at signature creation date +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_CertNotYetValidAtSig; + +/// list of attributes to be signed contains attribute that is not signable +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_AttributeNotSignable; + +/// signature verification failed because the signature contains an attribute that is not signable +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_VerificationFailed_AttributeNotSignable; + +/// selected dataset or item is empty, nothing to sign +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_DatasetEmpty; + +/// cannot create signature for current signature profile: required attributes missing +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_RequiredAttributeMissing; + +/// cannot handle ECDSA signatures because OpenSSL was compiled without elliptic curve support +/// @remark this constant is only available if DCMTK is compiled with OpenSSL support enabled. +extern DCMTK_DCMSIGN_EXPORT const OFConditionConst SI_EC_EllipticCurveNotSupported; + #endif #endif diff --git a/dcmsign/libsrc/CMakeLists.txt b/dcmsign/libsrc/CMakeLists.txt index d3812810..db078fe1 100644 --- a/dcmsign/libsrc/CMakeLists.txt +++ b/dcmsign/libsrc/CMakeLists.txt @@ -1,5 +1,9 @@ # create library from source files -DCMTK_ADD_LIBRARY(dcmdsig dcsignat siautopr sibrsapr sicert sicertvf sicreapr sidsa simaccon simd5 sinullpr siprivat siripemd sirsa sisha1 sisprof sitypes sisha256 sisha384 sisha512) +DCMTK_ADD_LIBRARY( + dcmdsig dcsighlp dcsignat siautopr sibrsapr sicert sicertvf sicreapr + sidsa siecdsa simaccon simd5 sinullpr siprivat sipurpos siripemd sirsa + sisha1 sisprof sisrpr sisrvpr sitstamp sitypes sisha256 sisha384 + sisha512 sitsfs) DCMTK_TARGET_LINK_MODULES(dcmdsig ofstd dcmdata) DCMTK_TARGET_LINK_LIBRARIES(dcmdsig ${OPENSSL_LIBS}) diff --git a/dcmsign/libsrc/Makefile.dep b/dcmsign/libsrc/Makefile.dep index 5e03274a..e60234d7 100644 --- a/dcmsign/libsrc/Makefile.dep +++ b/dcmsign/libsrc/Makefile.dep @@ -1,3 +1,74 @@ +dcsighlp.o: dcsighlp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/dcsighlp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ + ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../include/dcmtk/dcmsign/dcsignat.h ../include/dcmtk/dcmsign/sicert.h \ + ../include/dcmtk/dcmsign/sicertvf.h ../include/dcmtk/dcmsign/sisprof.h \ + ../include/dcmtk/dcmsign/sitsfs.h ../include/dcmtk/dcmsign/sitstamp.h \ + ../include/dcmtk/dcmsign/sicreapr.h ../include/dcmtk/dcmsign/sibrsapr.h \ + ../include/dcmtk/dcmsign/siautopr.h ../include/dcmtk/dcmsign/sisrvpr.h \ + ../include/dcmtk/dcmsign/sisrpr.h \ + ../../ofstd/include/dcmtk/ofstd/ofexit.h dcsignat.o: dcsignat.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/dcsignat.h ../include/dcmtk/dcmsign/sitypes.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ @@ -40,6 +111,7 @@ dcsignat.o: dcsignat.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../ofstd/include/dcmtk/ofstd/offile.h \ @@ -76,7 +148,7 @@ dcsignat.o: dcsignat.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/siripemd.h ../include/dcmtk/dcmsign/sisha1.h \ ../include/dcmtk/dcmsign/sisha256.h ../include/dcmtk/dcmsign/sisha384.h \ ../include/dcmtk/dcmsign/sisha512.h ../include/dcmtk/dcmsign/sisprof.h \ - ../include/dcmtk/dcmsign/sitstamp.h + ../include/dcmtk/dcmsign/sitstamp.h ../include/dcmtk/dcmsign/sitsfs.h siautopr.o: siautopr.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/siautopr.h ../include/dcmtk/dcmsign/sibrsapr.h \ ../include/dcmtk/dcmsign/sisprof.h ../include/dcmtk/dcmsign/sitypes.h \ @@ -113,7 +185,7 @@ siautopr.o: siautopr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmsign/sidefine.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ @@ -121,7 +193,20 @@ siautopr.o: siautopr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h sibrsapr.o: sibrsapr.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/sibrsapr.h ../include/dcmtk/dcmsign/sisprof.h \ ../include/dcmtk/dcmsign/sitypes.h \ @@ -158,7 +243,7 @@ sibrsapr.o: sibrsapr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmsign/sidefine.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ @@ -204,6 +289,7 @@ sicert.o: sicert.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sirsa.h \ ../include/dcmtk/dcmsign/sialgo.h ../include/dcmtk/dcmsign/sidsa.h \ + ../include/dcmtk/dcmsign/siecdsa.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ @@ -228,7 +314,10 @@ sicert.o: sicert.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h sicertvf.o: sicertvf.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/sicert.h ../include/dcmtk/dcmsign/sitypes.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ @@ -301,7 +390,7 @@ sicreapr.o: sicreapr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmsign/sidefine.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ @@ -309,7 +398,20 @@ sicreapr.o: sicreapr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ ../../ofstd/include/dcmtk/ofstd/ofthread.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ - ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h sidsa.o: sidsa.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/sidsa.h ../include/dcmtk/dcmsign/sialgo.h \ ../include/dcmtk/dcmsign/sitypes.h \ @@ -348,6 +450,44 @@ sidsa.o: sidsa.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sicert.h \ ../include/dcmtk/dcmsign/siprivat.h +siecdsa.o: siecdsa.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/siecdsa.h ../include/dcmtk/dcmsign/sialgo.h \ + ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sicert.h \ + ../include/dcmtk/dcmsign/siprivat.h simaccon.o: simaccon.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/simaccon.h ../include/dcmtk/dcmsign/sitypes.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ @@ -488,7 +628,7 @@ sinullpr.o: sinullpr.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmsign/sidefine.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ @@ -532,7 +672,64 @@ siprivat.o: siprivat.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sirsa.h \ ../include/dcmtk/dcmsign/sialgo.h ../include/dcmtk/dcmsign/sidsa.h \ - ../include/dcmtk/dcmsign/sicert.h + ../include/dcmtk/dcmsign/siecdsa.h ../include/dcmtk/dcmsign/sicert.h +sipurpos.o: sipurpos.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/sipurpos.h ../include/dcmtk/dcmsign/sidefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h siripemd.o: siripemd.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/siripemd.h ../include/dcmtk/dcmsign/simac.h \ ../include/dcmtk/dcmsign/sitypes.h \ @@ -801,7 +998,7 @@ sisprof.o: sisprof.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ - ../include/dcmtk/dcmsign/sidefine.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ @@ -824,7 +1021,253 @@ sisprof.o: sisprof.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../include/dcmtk/dcmsign/simac.h ../include/dcmtk/dcmsign/sialgo.h + ../include/dcmtk/dcmsign/simac.h ../include/dcmtk/dcmsign/sialgo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h +sisrpr.o: sisrpr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/sisrpr.h ../include/dcmtk/dcmsign/sibrsapr.h \ + ../include/dcmtk/dcmsign/sisprof.h ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +sisrvpr.o: sisrvpr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/sisrvpr.h ../include/dcmtk/dcmsign/sisrpr.h \ + ../include/dcmtk/dcmsign/sibrsapr.h ../include/dcmtk/dcmsign/sisprof.h \ + ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmsign/sidefine.h ../include/dcmtk/dcmsign/sipurpos.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +sitsfs.o: sitsfs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/sitsfs.h ../include/dcmtk/dcmsign/sitstamp.h \ + ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmsign/sidefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h +sitstamp.o: sitstamp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmsign/sitstamp.h ../include/dcmtk/dcmsign/sitypes.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmsign/sidefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmsign/simd5.h ../include/dcmtk/dcmsign/simac.h \ + ../include/dcmtk/dcmsign/siripemd.h ../include/dcmtk/dcmsign/sisha1.h \ + ../include/dcmtk/dcmsign/sisha256.h ../include/dcmtk/dcmsign/sisha384.h \ + ../include/dcmtk/dcmsign/sisha512.h ../include/dcmtk/dcmsign/sicert.h \ + ../include/dcmtk/dcmsign/sicertvf.h ../include/dcmtk/dcmsign/dcsignat.h \ + ../include/dcmtk/dcmsign/sipurpos.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h sitypes.o: sitypes.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/dcmsign/sitypes.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ diff --git a/dcmsign/libsrc/Makefile.in b/dcmsign/libsrc/Makefile.in index 4576b165..511a340c 100644 --- a/dcmsign/libsrc/Makefile.in +++ b/dcmsign/libsrc/Makefile.in @@ -21,9 +21,10 @@ LOCALDEFS = objs = dcsignat.o sicert.o sidsa.o simd5.o siprivat.o sirsa.o sisprof.o \ siautopr.o sicreapr.o simaccon.o sinullpr.o siripemd.o sisha1.o \ - sitypes.o sicertvf.o sibrsapr.o sisha256.o sisha384.o sisha512.o -library = libdcmdsig.$(LIBEXT) + sitypes.o sicertvf.o sibrsapr.o sisha256.o sisha384.o sisha512.o siecdsa.o \ + sisrpr.o sisrvpr.o sipurpos.o dcsighlp.o sitstamp.o sitsfs.o +library = libdcmdsig.$(LIBEXT) all: $(library) diff --git a/dcmsign/libsrc/dcsighlp.cc b/dcmsign/libsrc/dcsighlp.cc new file mode 100644 index 00000000..ff9f966f --- /dev/null +++ b/dcmsign/libsrc/dcsighlp.cc @@ -0,0 +1,984 @@ +/* + * + * Copyright (C) 2000-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: DcmSignatureHelper + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/dcsighlp.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for attribute tag constants */ +#include "dcmtk/dcmdata/dcdicent.h" /* for class DcmDictEntry */ +#include "dcmtk/dcmdata/dcdict.h" /* for class DcmDataDictionary */ +#include "dcmtk/dcmdata/dcitem.h" /* for class DcmItem */ +#include "dcmtk/dcmdata/dcsequen.h" /* for class DcmSequenceOfItems */ +#include "dcmtk/dcmdata/dcvrat.h" /* for class DcmAttributeTag */ +#include "dcmtk/dcmsign/dcsignat.h" /* for class DcmSignature */ +#include "dcmtk/dcmsign/sicert.h" /* for class SiCertificate */ +#include "dcmtk/dcmsign/sicertvf.h" /* for class SiCertificateVerifier */ +#include "dcmtk/dcmsign/sisprof.h" /* for class SiSecurityProfile */ +#include "dcmtk/dcmsign/sitsfs.h" /* for class SiTimeStampFS */ +#include "dcmtk/dcmsign/sitypes.h" /* for logger macros */ +#include "dcmtk/dcmsign/sicreapr.h" /* for class SiCreatorProfile */ +#include "dcmtk/dcmsign/siautopr.h" /* for class SiAuthorizationProfile */ +#include "dcmtk/dcmsign/sisrvpr.h" /* for class SiStructuredReportingVerificationProfile */ +#include "dcmtk/ofstd/ofexit.h" /* for common exit codes */ +#include "dcmtk/dcmsign/siexit.h" /* for dcmsign specific exit codes */ + + +DcmSignatureHelper::DcmSignatureHelper() +{ +} + +DcmSignatureHelper::~DcmSignatureHelper() +{ +} + +int DcmSignatureHelper::readNextToken(const char *c, int& pos, DcmTagKey& key, Uint32& idx) +{ + OFString aString; + int lpos = pos; + int spos = 0; + while(isspace(OFstatic_cast(unsigned char, c[lpos]))) ++lpos; // ignore leading space + + if (c[lpos]=='\0') return -1; // EOF + if (c[lpos]=='.') + { + ++pos; + return 3; // period + } + if (c[lpos]=='[') + { + spos = ++lpos; + while ((c[lpos] >= '0')&&(c[lpos] <= '9')) ++lpos; + if (c[lpos] != ']') return 0; // parse error + unsigned long newindex = 0; + if (1 != sscanf(c+spos,"%lu", &newindex)) return 0; // parse error + idx = OFstatic_cast(Uint32, newindex); + pos = ++lpos; + return 2; // index + } + if (c[lpos]=='(') + { + spos = ++lpos; + while ((c[lpos] != ')')&&(c[lpos] != '\0')) ++lpos; + if (c[lpos] != ')') return 0; // parse error + unsigned int group=0; + unsigned int elem=0; + if (2 != sscanf(c+spos,"%x,%x", &group, &elem)) return 0; // parse error + key = DcmTagKey(group,elem); + pos = ++lpos; + return 1; // tag key + } + spos = lpos; + while ( ((c[lpos] >= 'a')&&(c[lpos] <= 'z')) || ((c[lpos] >= 'A')&&(c[lpos] <= 'Z')) || ((c[lpos] >= '0')&&(c[lpos] <= '9'))) ++lpos; + aString.append(c + spos, (lpos-spos)); + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(aString.c_str()); + if (dicent) + { + key = dicent->getKey(); + dcmDataDict.rdunlock(); + pos = lpos; + return 1; // tag key; + } + dcmDataDict.rdunlock(); + DCMSIGN_ERROR("attribute name '" << aString.c_str() << "' unknown."); + return 0; // parse error +} + + +char *DcmSignatureHelper::readTextFile(const char *filename) +{ + char *result = NULL; + FILE *file = fopen(filename, "rb"); + if (file) + { + fseek(file, 0, SEEK_END); + long numBytes = ftell(file); + fseek(file, 0, SEEK_SET); + result = new char[numBytes+1]; + if (result) + { + result[numBytes] = '\0'; // ensure zero termination of text field + if (OFstatic_cast(size_t, numBytes) != fread(result, 1, OFstatic_cast(size_t, numBytes), file)) + { + DCMSIGN_WARN("read error in file " << filename); + delete[] result; + result = NULL; + } + } + fclose(file); + } else { + DCMSIGN_ERROR("file not found: " << filename); + } + return result; +} + + +int DcmSignatureHelper::parseTextFile(const char *filename, DcmAttributeTag& tagList) +{ + char *c=readTextFile(filename); + if (c==NULL) return EXITCODE_CANNOT_READ_TAG_FILE; // bail out + int position = 0; + int token = 0; + Uint32 idx = 0; + DcmTagKey key; + int result = EXITCODE_NO_ERROR; + do + { + token = readNextToken(c, position, key, idx); + if (token == 1) // we have read a tag key + { + if (EC_Normal != tagList.putTagVal(key, tagList.getVM())) + { + result = EXITCODE_SYNTAX_ERROR_IN_TAG_FILE; + token = -1; + } + } + else if (token >= 0) + { + DCMSIGN_ERROR("parse error in text file '" << filename << "'"); + result = EXITCODE_SYNTAX_ERROR_IN_TAG_FILE; + token = -1; + } + } while (token >= 0); + delete[] c; + return result; +} + + +OFBool DcmSignatureHelper::addTag(const char *c, DcmAttributeTag& tagList) +{ + OFBool result = OFFalse; + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + if (sscanf(c, "%x,%x", &group, &elem ) != 2 ) + { + /* it is a name */ + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(c); + if (dicent) + { + if (EC_Normal == tagList.putTagVal(dicent->getKey(), tagList.getVM())) result = OFTrue; + } + dcmDataDict.rdunlock(); + } else { + if (EC_Normal == tagList.putTagVal(DcmTagKey(group,elem), tagList.getVM())) result = OFTrue; + } + return result; +} + + +DcmItem *DcmSignatureHelper::locateItemforSignatureCreation(DcmItem& dataset, const char *location) +{ + DcmTagKey key; + Uint32 idx; + int pos = 0; + int token = 0; + int expected = 1; + OFBool finished = OFFalse; + DcmItem *result = &dataset; + DcmSequenceOfItems *sq = NULL; + DcmStack stack; + do + { + token = readNextToken(location, pos, key, idx); + if ((token != expected)&&(token != -1)) + { + DCMSIGN_ERROR("parse error in item location string '" << location << "'"); + return NULL; + } + if (token == -1) + { + if (! finished) + { + DCMSIGN_ERROR("item location string '" << location << "' incomplete."); + return NULL; + } + return result; + } + if (token == 1) + { + // we have read a tag key + stack.clear(); + if (EC_Normal != result->search(key, stack, ESM_fromHere, OFFalse)) + { + DCMSIGN_ERROR("attribute " << key << " not found in dataset (item location string is '" << location << "')"); + return NULL; + } + if (stack.top()->ident() == EVR_SQ) + { + sq = OFstatic_cast(DcmSequenceOfItems *, (stack.top())); + } else { + DCMSIGN_ERROR("attribute " << key << " is not a sequence (item location string is '" << location << "')"); + return NULL; + } + expected = 2; + finished = OFFalse; + } + else if (token == 2) + { + // we have read an index + if (sq == NULL) + { + DCMSIGN_ERROR("sequence not found in item location string '" << location << "'"); + return NULL; + } + if (idx >= sq->card()) + { + DCMSIGN_ERROR("sequence " << sq->getTag() << " only has " << sq->card() + << " items, cannot locate item " << idx << " (item location string is '" << location << "')"); + return NULL; + } + result = sq->getItem(idx); + if (result == NULL) + { + DCMSIGN_ERROR("item not found in item location string '" << location << "'"); + return NULL; + } + expected = 3; + finished = OFTrue; + } + else if (token == 3) + { + // we have read a period + expected = 1; + finished = OFFalse; + } + } while (token > 0); + return NULL; +} + + +void DcmSignatureHelper::printSignatureItemPosition(DcmStack& stack, OFString& str) +{ + str.clear(); + DcmObject *elem = NULL; + DcmSequenceOfItems *sq = NULL; + unsigned long sqCard=0; + const char *tagname = NULL; + unsigned long m=0; + char buf[30]; + if (stack.card() > 2) + { + // signature is located within a sequence + for (unsigned long l=stack.card()-2; l>0; --l) // loop over all elements except the stack top and bottom + { + elem = stack.elem(l); + if (elem) + { + if ((elem->ident() == EVR_item) && sq) + { + sqCard = sq->card(); + for (m=0; mgetItem(m) == elem) + { + sprintf(buf, "[%lu]", m); + str.append(buf); + } + } + } + else + { + if (str.size() > 0) str.append("."); + sq = OFstatic_cast(DcmSequenceOfItems *, elem); + DcmTag currentTag(elem->getTag()); + tagname = currentTag.getTagName(); + if (tagname) str.append(tagname); else + { + sprintf(buf, "(%04x,%04x)", elem->getTag().getGroup(), elem->getTag().getElement()); + str.append(buf); + } + if (elem->ident() == EVR_SQ) sq = OFstatic_cast(DcmSequenceOfItems *, elem); else sq = NULL; + } + } + } + } else { + // signature is located in the main dataset + str = "Main Dataset"; + } +} + + +int DcmSignatureHelper::do_sign( + DcmItem *dataset, + SiPrivateKey& key, + SiCertificate& cert, + SiMAC *opt_mac, + SiSecurityProfile *opt_profile, + DcmAttributeTag *opt_tagList, + E_TransferSyntax opt_signatureXfer, + FILE *dumpFile, + SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose, + SiTimeStamp *timeStamp) +{ + OFCondition sicond = opt_profile->inspectSignatureDataset(*dataset); + if (sicond.good()) + { + DcmSignature signer; + signer.attach(dataset); + signer.setDumpFile(dumpFile); + sicond = signer.createSignature(key, cert, *opt_mac, *opt_profile, opt_signatureXfer, opt_tagList, timeStamp, opt_sigPurpose); + signer.detach(); + } + + if (sicond.bad()) + { + DCMSIGN_ERROR(sicond.text() << " while creating signature in main dataset"); + return EXITCODE_SIGNATURE_CREATION_FAILED; + } + return EXITCODE_NO_ERROR; +} + + +int DcmSignatureHelper::do_sign_item( + DcmItem *dataset, + SiPrivateKey& key, + SiCertificate& cert, + SiMAC *opt_mac, + SiSecurityProfile *opt_profile, + DcmAttributeTag *opt_tagList, + const char *opt_location, + E_TransferSyntax opt_signatureXfer, + FILE *dumpFile, + SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose, + SiTimeStamp *timeStamp) +{ + OFCondition sicond = EC_Normal; + DcmItem *sigItem = locateItemforSignatureCreation(*dataset, opt_location); + if (sigItem == NULL) sicond = SI_EC_ItemLocationNotFound; + else + { + sicond = opt_profile->inspectSignatureDataset(*sigItem); + if (sicond.good()) + { + DcmSignature signer; + signer.attach(sigItem); + signer.setDumpFile(dumpFile); + sicond = signer.createSignature(key, cert, *opt_mac, *opt_profile, opt_signatureXfer, opt_tagList, timeStamp, opt_sigPurpose); + signer.detach(); + } + } + + if (sicond.bad()) + { + DCMSIGN_ERROR(sicond.text() << " while creating signature in item '" << opt_location << "'"); + return EXITCODE_SIGNATURE_CREATION_FAILED; + } + return EXITCODE_NO_ERROR; +} + + +int DcmSignatureHelper::do_verify( + DcmItem *dataset, + SiCertificateVerifier& certVerifier, + E_SignatureVerificationPolicy verificationPolicy, + E_TimestampVerificationPolicy timestampPolicy) +{ + OFCondition sicond = EC_Normal; + DcmStack stack; + DcmSignature signer; + OFString aString; + + // this counter counts the number of signatures found in the dataset + int counter = 0; + + // this counter contains the number of signatures in the dataset + // that have failed validation + int corrupt_counter = 0; + + unsigned long numSignatures = 0; + unsigned long l=0; + DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); + + // this flag is set to true if we find any signature in the dataset + // that complies with the verification policy. + OFBool verificationPolicyFulfilled = OFFalse; + const char *verificationPolicyName = "(undefined)"; + OFString s; + + // for these verification policies, there is nothing to check, + // ESVP_requireSignature is checked elsewhere. + if ((verificationPolicy == ESVP_verifyIfPresent) || + (verificationPolicy == ESVP_requireSignature)) + verificationPolicyFulfilled = OFTrue; + + while (sigItem) + { + signer.attach(sigItem); + numSignatures = signer.numberOfSignatures(); + for (l=0; lfindAndGetOFString(DCM_VerificationFlag, s).good() && (s == "VERIFIED")) + { + SiStructuredReportingVerificationProfile sprofSRV; + verificationPolicyFulfilled = signer.verifySignatureProfile(sprofSRV).good(); + } + else + { + SiStructuredReportingProfile sprofSR; + verificationPolicyFulfilled = signer.verifySignatureProfile(sprofSR).good(); + } + } + } + break; + case ESVP_verifyIfPresent: + case ESVP_requireSignature: + break; + // There is deliberately no default here because if we extend + // the enum then we will have to extend this code. + } + + // first verify if the signature matches the dataset + sicond = signer.verifyCurrent(); + if (sicond.good()) + { + // now check if we can successfully verify the signer's certificate + SiCertificate *cert = signer.getCurrentCertificate(); + if (cert) + { + // print a warning if we have a weak (i.e. too short) key in the certificate + cert->checkForWeakKey(); + + if (certVerifier.verifyCertificate(*cert).good()) + { + DCMSIGN_WARN(aString << "OK"); + checkTimestamp = OFTrue; + } + else + { + cert_expiry = certVerifier.lastErrorIsCertExpiry(); + DCMSIGN_WARN(aString << "signature is OK but certificate verification failed: " << certVerifier.lastError()); + corrupt_counter++; + } + } + else + { + DCMSIGN_WARN(aString << "failed, certificate empty or invalid"); + corrupt_counter++; + } + } else { + DCMSIGN_WARN(aString << sicond.text()); + corrupt_counter++; + } + + // check certified timestamp (if any). + // We only do this if the signature verification has passed + // or if the signature is OK but the signer certificate has expired, + // which may be "healed" by a timestamp that is still valid + if (checkTimestamp || cert_expiry) + { + printTimestampDetails(signer, timestampPolicy); + + SiTimeStamp *tstamp = signer.getCurrentTimestamp(); + OFBool haveTS = (tstamp != NULL) && tstamp->have_tsinfo(); + if (haveTS) + { + if (timestampPolicy != ETVP_ignoreTS) + { + // timestamp is present and according to our policy we should verify it + if (dcmsignLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) + aString = " Timestamp Verification : "; + else aString = " Timestamp Verification : "; + + sicond = tstamp->verifyTSSignature(certVerifier); + if (sicond.good()) + { + sicond = tstamp->verifyTSToken(certVerifier, *signer.getSelectedSignatureItem(), *signer.getCurrentCertificate()); + if (sicond.good()) + { + if (cert_expiry) + { + // we have an expired signature but a timestamp that is still valid, + // which means that the timestamp "heals" the failed signature verification + corrupt_counter--; + DCMSIGN_WARN(aString << "OK, extends validity period of expired signature."); + } + else + { + DCMSIGN_WARN(aString << "OK"); + } + } + else + { + OFString errString; + tstamp->lastError(errString); // check if we have an OpenSSL error message + if (errString.length() == 0) errString = sicond.text(); // use DCMTK error message otherwise + DCMSIGN_WARN(aString << "timestamp signature verification failed: " << errString); + if (!cert_expiry) corrupt_counter++; // if cert_expiry is true, the counter has already been increased + } + } + else + { + OFString errString; + tstamp->lastError(errString); + DCMSIGN_WARN(aString << "timestamp signature verification failed: " << errString); + if (!cert_expiry) corrupt_counter++; // if cert_expiry is true, the counter has already been increased + } + } + } + else + { + // no timestamp present. Check if this is a problem. + if (timestampPolicy == ETVP_requireTS) + { + DCMSIGN_WARN(" Certified timestamp : absent, but required by timestamp policy"); + if (!cert_expiry) corrupt_counter++; // if cert_expiry is true, the counter has already been increased + } + } + } // if (checkTimestamp) + } // if (EC_Normal == signer.selectSignature(l)) + } // for (l=0; l 0) + { + ++counter; + if (EC_Normal == signer.selectSignature(0)) + { + if (EC_Normal == signer.getCurrentSignatureUID(aString)) + DCMSIGN_WARN("Signature #" << counter << " UID=" << aString); + else + DCMSIGN_WARN("Signature #" << counter << " UID=(unknown)"); + printSignatureItemPosition(stack, aString); + DCMSIGN_WARN(" Location : " << aString); + } + sicond = signer.removeSignature(0); + if (sicond != EC_Normal) + { + DCMSIGN_ERROR(sicond.text() << ": while removing signature"); + return EXITCODE_SIGNATURE_REMOVAL_FAILED; + } + } + signer.detach(); + stack.pop(); // remove pointer to the Digital Signatures Sequence that we've just deleted. + sigItem = DcmSignature::findNextSignatureItem(*dataset, stack); + } + DCMSIGN_INFO(counter << " signatures found and removed from dataset."); + return EXITCODE_NO_ERROR; +} + + +int DcmSignatureHelper::do_remove( + DcmItem *dataset, + const char *opt_location) +{ + OFCondition sicond = EC_Normal; + DcmSignature signer; + OFString aString; + DcmStack stack; + unsigned long cardSQ; + unsigned long i; + DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); + while (sigItem) + { + signer.attach(sigItem); + cardSQ = signer.numberOfSignatures(); + for (i=0; iload_ts_query_from_file().bad()) + { + return EXITCODE_CANNOT_READ_TSQ_FILE; + } + + // load timestamp response + if (timeStamp->load_ts_response_from_file().bad()) + { + return EXITCODE_CANNOT_READ_TSR_FILE; + } + + // load digital signature UID + OFString uid; + OFCondition result = timeStamp->getUIDFromFile(uid); + if (result.bad()) return EXITCODE_CANNOT_READ_UID_FILE; + + // locate digital signature + DcmSignature signer; + OFString currentUID; + DcmStack stack; + unsigned long cardSQ; + unsigned long i; + OFBool found = OFFalse; + + DcmItem *sigItem = DcmSignature::findFirstSignatureItem(*dataset, stack); + while (sigItem) + { + // attach the item in which a digital signatures sequence was found + signer.attach(sigItem); + // determine the number of signatures in this item + cardSQ = signer.numberOfSignatures(); + for (i=0; icheck_ts_response(*currentSignatureItem); + if (result.bad()) return EXITCODE_TS_CONSISTENCY_CHECK_FAILED; + + // write timestamp to dataset + result = timeStamp->write_ts_token(*currentSignatureItem); + if (result.bad()) return EXITCODE_CANNOT_INSERT_TS; + } + } + } + signer.detach(); + if (found) sigItem = NULL; else sigItem = DcmSignature::findNextSignatureItem(*dataset, stack); + } + + if (!found) + { + DCMSIGN_ERROR("signature with UID '" << uid << "' not found."); + return EXITCODE_SIGNATURE_UID_NOT_FOUND; + } + return EXITCODE_NO_ERROR; +} + + +void DcmSignatureHelper::printSignatureDetails(DcmSignature& sig, DcmStack& stack, int count) +{ + OFString aString; + OFString codeValue; + OFString codeMeaning; + OFString codingSchemeDesignator; + Uint16 macID = 0; + DcmAttributeTag at(DCM_DataElementsSigned); + DcmTagKey tagkey; + DcmTag tag; + const char *tagName = NULL; + + if (EC_Normal == sig.getCurrentSignatureUID(aString)) + DCMSIGN_WARN("Signature #" << count << " UID=" << aString); + else + DCMSIGN_WARN("Signature #" << count << " UID=" << "(unknown)"); + printSignatureItemPosition(stack, aString); + if (dcmsignLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) + { + DCMSIGN_INFO(" Location : " << aString); + if (EC_Normal == sig.getCurrentMacID(macID)) + DCMSIGN_INFO(" MAC ID : " << macID); + else + DCMSIGN_INFO(" MAC ID : (unknown)"); + if (EC_Normal == sig.getCurrentMacName(aString)) + DCMSIGN_INFO(" MAC algorithm : " << aString); + else + DCMSIGN_INFO(" MAC algorithm : (unknown)"); + if (EC_Normal == sig.getCurrentMacXferSyntaxName(aString)) + DCMSIGN_INFO(" MAC calculation xfer syntax : " << aString); + else + DCMSIGN_INFO(" MAC calculation xfer syntax : (unknown)"); + // data elements signed + if (EC_Normal != sig.getCurrentDataElementsSigned(at)) + DCMSIGN_INFO(" Data elements signed : (unknown)"); + else + { + DCMSIGN_INFO(" Data elements signed :"); + unsigned long atVM = at.getVM(); + for (unsigned long n=0; ngetKeyType()==EKT_none)) + DCMSIGN_INFO(" none"); + else + { + DCMSIGN_INFO(" X.509v" << cert->getX509Version()); + cert->getCertSubjectName(aString); + DCMSIGN_INFO(" Subject : " << aString); + cert->getCertIssuerName(aString); + DCMSIGN_INFO(" Issued by : " << aString); + DCMSIGN_INFO(" Serial no. : " << cert->getCertSerialNo()); + cert->getCertValidityNotBefore(aString); + DCMSIGN_INFO(" Validity : not before " << aString); + cert->getCertValidityNotAfter(aString); + DCMSIGN_INFO(" Validity : not after " << aString); + const char *ecname = NULL; + switch (cert->getKeyType()) + { + case EKT_RSA: + DCMSIGN_INFO(" Public key : RSA, " << cert->getCertKeyBits() << " bits"); + break; + case EKT_DSA: + DCMSIGN_INFO(" Public key : DSA, " << cert->getCertKeyBits() << " bits"); + break; + case EKT_EC: + ecname = cert->getCertCurveName(); + if (ecname) + { + DCMSIGN_INFO(" Public key : EC, curve " << ecname << ", " << cert->getCertKeyBits() << " bits"); + } + else + { + DCMSIGN_INFO(" Public key : EC, " << cert->getCertKeyBits() << " bits"); + } + break; + case EKT_DH: + DCMSIGN_INFO(" Public key : DH, " << cert->getCertKeyBits() << " bits"); + break; + default: + case EKT_none: // should never happen + DCMSIGN_INFO(" Public key : unknown type"); + break; + } + } + } else { + DCMSIGN_INFO(" Location : " << aString); + } +} + + +void DcmSignatureHelper::printTimestampDetails(DcmSignature& sig, E_TimestampVerificationPolicy tsPolicy) +{ + SiTimeStamp *tstamp = sig.getCurrentTimestamp(); + OFBool haveTS = (tstamp != NULL) && tstamp->have_tsinfo(); + + if (dcmsignLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) + { + switch (tsPolicy) + { + case ETVP_verifyTSIfPresent: + if (haveTS) + { + DCMSIGN_INFO(" Certified timestamp : CMS_TSP version " << tstamp->get_tsinfo_version()); + } + else + { + DCMSIGN_INFO(" Certified timestamp : absent"); + return; + } + break; + case ETVP_ignoreTS: + if (haveTS) + { + DCMSIGN_INFO(" Certified timestamp : present, but ignored according to timestamp policy"); + return; + } + else + { + DCMSIGN_INFO(" Certified timestamp : absent"); + return; + } + break; + + case ETVP_requireTS: + if (haveTS) + { + DCMSIGN_INFO(" Certified timestamp : CMS_TSP version " << tstamp->get_tsinfo_version()); + } + else + { + DCMSIGN_INFO(" Certified timestamp : absent, but required by timestamp policy"); + return; + } + break; + } + } + + if (haveTS) + { + // Now print timestamp details + OFString s; + tstamp->get_tsinfo_policy_oid(s); + DCMSIGN_INFO(" Policy OID : " << s); + tstamp->get_tsinfo_imprint_algorithm_name(s); + DCMSIGN_INFO(" Imprint MAC algorithm : " << s); + tstamp->get_tsinfo_serial_number(s); + DCMSIGN_INFO(" Serial number : " << s); + tstamp->get_tsinfo_nonce(s); + if (s.length() == 0) s = "none"; + DCMSIGN_INFO(" Nonce : " << s); + tstamp->get_tsinfo_tsa_name(s); + if (s.length() == 0) s = "none"; + DCMSIGN_INFO(" TSA Name : " << s); + DCMSIGN_INFO(" Ordering : " << (tstamp->get_tsinfo_ordering() ? "true" : "false" )); + tstamp->get_tsinfo_accuracy(s); + if (s.length() == 0) s = "not specified"; + DCMSIGN_INFO(" Accuracy : " << s); + tstamp->get_tsinfo_timestamp(s); + DCMSIGN_INFO(" Timestamp : " << s); + tstamp->get_tsinfo_policy_oid(s); + + // finally, print extensions (if any) + int numext = tstamp->get_tsinfo_numextensions(); + if (numext == 0) + { + DCMSIGN_INFO(" Extensions : none"); + } + else + { + DCMSIGN_INFO(" Extensions :"); + for (int i=0; iget_tsinfo_extension(s, i); + DCMSIGN_INFO(" - " << s); + } + } + } +} + + + +#else /* WITH_OPENSSL */ + +int sisighlp_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/dcsignat.cc b/dcmsign/libsrc/dcsignat.cc index 19393cf8..e22ab23e 100644 --- a/dcmsign/libsrc/dcsignat.cc +++ b/dcmsign/libsrc/dcsignat.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2010, OFFIS e.V. + * Copyright (C) 2000-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -33,10 +33,11 @@ #include "dcmtk/dcmdata/dcvrui.h" #include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcvrdt.h" #include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcsequen.h" #include "dcmtk/dcmdata/dcdeftag.h" - +#include "dcmtk/ofstd/ofstd.h" #include "dcmtk/dcmsign/sialgo.h" #include "dcmtk/dcmsign/sicert.h" #include "dcmtk/dcmsign/simac.h" @@ -50,6 +51,7 @@ #include "dcmtk/dcmsign/sisha512.h" #include "dcmtk/dcmsign/sisprof.h" #include "dcmtk/dcmsign/sitstamp.h" +#include "dcmtk/dcmsign/sitsfs.h" BEGIN_EXTERN_C #include @@ -65,21 +67,21 @@ void DcmSignature::initializeLibrary() ERR_load_crypto_strings(); } - -Uint16 DcmSignature::getMACIDnumber(DcmItem &item) +OFCondition DcmSignature::getMACIDnumber(DcmItem &item, Uint16& macid) { - Uint16 macIDnumber = 0; + macid = 0xFFFF; DcmStack stack; - if (item.search(DCM_MACIDNumber, stack, ESM_fromHere, OFFalse).good() && (stack.top()->isLeaf())) + OFCondition result = item.search(DCM_MACIDNumber, stack, ESM_fromHere, OFFalse); + if (result.good() && (stack.top()->isLeaf())) { - ((DcmElement *)(stack.top()))->getUint16(macIDnumber); + result = ((DcmElement *)(stack.top()))->getUint16(macid); } - return macIDnumber; + return result; } - void DcmSignature::currentDateTime(OFString &str) { + str = ""; DcmDateTime::getCurrentDateTime(str, OFTrue /*seconds*/, OFTrue /*fraction*/, OFTrue /*timeZone*/); } @@ -95,6 +97,7 @@ DcmSignature::DcmSignature() , selectedSignatureItem(NULL) , selectedMacParametersItem(NULL) , selectedCertificate(NULL) +, selectedTimestamp(NULL) { } @@ -111,6 +114,8 @@ void DcmSignature::deselect() selectedMacParametersItem = NULL; delete selectedCertificate; selectedCertificate = NULL; + delete selectedTimestamp; + selectedTimestamp = NULL; } @@ -167,15 +172,19 @@ OFCondition DcmSignature::removeSignature(unsigned long i) DcmItem *removalItem = signatureSq->getItem(i); if (removalItem == NULL) return EC_IllegalCall; // should never happen + Uint16 macIDnumber = 0; + OFCondition result = getMACIDnumber(*removalItem, macIDnumber); + if (result.bad()) return result; + // check mac ID number and whether it is unique - Uint16 macIDnumber = getMACIDnumber(*removalItem); OFBool macIDunique = OFTrue; DcmItem *tmpItem=NULL; unsigned long j=0; + Uint16 macIDnumber2 = 0; for (j=0; j < seqCard; ++j) { tmpItem = signatureSq->getItem(j); - if ((i != j) && tmpItem && (macIDnumber == getMACIDnumber(*tmpItem))) macIDunique = OFFalse; + if ((i != j) && tmpItem && (getMACIDnumber(*tmpItem, macIDnumber2).good()) && (macIDnumber == macIDnumber2)) macIDunique = OFFalse; } // delete signature item @@ -188,7 +197,7 @@ OFCondition DcmSignature::removeSignature(unsigned long i) while (j < macParametersSq->card()) { tmpItem = macParametersSq->getItem(j); - if (tmpItem && (macIDnumber == getMACIDnumber(*tmpItem))) delete macParametersSq->remove(j); else ++j; + if (tmpItem && (getMACIDnumber(*tmpItem, macIDnumber2).good()) && (macIDnumber == macIDnumber2)) delete macParametersSq->remove(j); else ++j; } } @@ -224,6 +233,7 @@ OFCondition DcmSignature::allocateMACID(Uint16& newID) if (isAllocated==NULL) return EC_MemoryExhausted; OFCondition result = SI_EC_MacIDsExhausted; + Uint16 macID = 0; for (i=0; i < 65536; ++i) isAllocated[i]=0; if (signatureSq) @@ -232,7 +242,10 @@ OFCondition DcmSignature::allocateMACID(Uint16& newID) for (i=0; i < sqCard; ++i) { tmpItem = signatureSq->getItem(i); - if (tmpItem) isAllocated[getMACIDnumber(*tmpItem)] = 1; + if (tmpItem && getMACIDnumber(*tmpItem, macID).good()) + { + isAllocated[macID] = 1; + } } } if (macParametersSq) @@ -241,7 +254,10 @@ OFCondition DcmSignature::allocateMACID(Uint16& newID) for (i=0; i < macCard; ++i) { tmpItem = macParametersSq->getItem(i); - if (tmpItem) isAllocated[getMACIDnumber(*tmpItem)] = 1; + if (tmpItem && getMACIDnumber(*tmpItem, macID).good()) + { + isAllocated[macID] = 1; + } } } i = 0; @@ -266,7 +282,8 @@ OFCondition DcmSignature::createSignature( SiSecurityProfile& profile, E_TransferSyntax xfer, const DcmAttributeTag *tagList, - SiTimeStamp *timeStamp) + SiTimeStamp *timeStamp, + SiSignaturePurpose::E_SignaturePurposeType sigPurpose) { // do some checks first if (currentItem == NULL) return EC_IllegalCall; @@ -277,7 +294,26 @@ OFCondition DcmSignature::createSignature( OFCondition result = EC_Normal; - // update tag list if present + // print a warning if we have a weak (i.e. too short) key in the certificate + cert.checkForWeakKey(); + + // print a warning if the certificate has already expired + if (cert.isCertExpiredNow()) + { + OFString expiry; + cert.getCertValidityNotAfter(expiry); + DCMSIGN_WARN("Certificate has expired " << expiry << ", signature will be invalid."); + } + + // print a warning if the certificate is not yet valid + if (cert.isCertNotYetValidNow()) + { + OFString notBefore; + cert.getCertValidityNotBefore(notBefore); + DCMSIGN_WARN("Certificate is not yet valid, validity starts " << notBefore << ", signature will be invalid."); + } + + // create updated tag list DcmAttributeTag *updatedTagList = NULL; if (tagList) { @@ -285,6 +321,12 @@ OFCondition DcmSignature::createSignature( if (updatedTagList == NULL) result = EC_MemoryExhausted; else result = profile.updateAttributeList(*currentItem, *updatedTagList); } + else + { + updatedTagList = new DcmAttributeTag(DCM_DataElementsSigned); + if (updatedTagList == NULL) result = EC_MemoryExhausted; + else result = profile.createAttributeList(*currentItem, *updatedTagList); + } // make sure we have a MAC parameter sequence if ((result.good()) && (macParametersSq == NULL)) @@ -369,6 +411,17 @@ OFCondition DcmSignature::createSignature( } else result = EC_MemoryExhausted; } + // Digital Signature Purpose Code Sequence + if (result.good()) + { + + // check if the signature profile requires a certain signature purpose + sigPurpose = SiSignaturePurpose::determineOverridePurpose(sigPurpose, profile.getOverrideSignaturePurpose()); + + // create digital signature purpose code sequence (unless sigPurpose is ESP_none) + result = SiSignaturePurpose::insertDigitalSignaturePurposeCodeSQ(*seqItem, sigPurpose); + } + // Certificate of Signer and Certificate Type if (result.good()) { @@ -386,6 +439,8 @@ OFCondition DcmSignature::createSignature( if (tagListOut == NULL) result = EC_MemoryExhausted; unsigned long sigLength = 0; unsigned char *signature = NULL; + unsigned long digestLength = mac.getSize(); + unsigned char *digest = new unsigned char[digestLength]; if (result.good()) { @@ -408,17 +463,20 @@ OFCondition DcmSignature::createSignature( } else result = EC_MemoryExhausted; } + // check whether all tags from tagList are really present in the signature + if (result.good()) + { + result = checkListOfSignedTags(tagList, tagListOut); + } + // sign MAC if (result.good()) { - unsigned long digestLength = mac.getSize(); - unsigned char *digest = new unsigned char[digestLength]; if (digest == NULL) result = EC_MemoryExhausted; else { result = mac.finalize(digest); if (result.good()) result = algorithm->sign(digest, digestLength, mac.macType(), signature, sigLength); - delete[] digest; } } @@ -449,7 +507,16 @@ OFCondition DcmSignature::createSignature( { if (timeStamp) { - // this would be the right time to request the time stamp + // now is the right time to request the certified time stamp + + // check if the digital signature has an odd number of bytes + if (algorithm->keyType() == EKT_DSA || algorithm->keyType() == EKT_EC) + { + // DSA and ECDSA signatures are encoded in DER and can have odd length. We must remove + // the pad byte before feeding the signature to the timestamping layer. + adjustASN1SequenceLength(signature, sigLength); + } + result = timeStamp->stamp(signature, sigLength); if (result.good()) { @@ -543,6 +610,7 @@ OFCondition DcmSignature::createSignature( } delete[] signature; + delete[] digest; delete tagListOut; delete updatedTagList; delete algorithm; @@ -557,15 +625,24 @@ OFCondition DcmSignature::selectSignature(unsigned long i) selectedSignatureItem = signatureSq->getItem(i); if (selectedSignatureItem == NULL) return EC_IllegalCall; - Uint16 macID = getMACIDnumber(*selectedSignatureItem); + + selectedMacParametersItem = NULL; + Uint16 macID = 0xFFFF; + OFCondition result = getMACIDnumber(*selectedSignatureItem, macID); + if (result.bad()) + { + DCMSIGN_WARN("Cannot read MAC ID number in DigitalSignaturesSequence."); + } + if (macParametersSq) { + Uint16 macID2 = 0; DcmItem *tmpItem=NULL; unsigned long cardMac = macParametersSq->card(); for (unsigned long j=0; jgetItem(j); - if (macID == getMACIDnumber(*tmpItem)) + if (result.good() && getMACIDnumber(*tmpItem, macID2).good() && macID == macID2) { selectedMacParametersItem = tmpItem; break; @@ -574,7 +651,25 @@ OFCondition DcmSignature::selectSignature(unsigned long i) } selectedCertificate = new SiCertificate(); if (selectedCertificate == NULL) return EC_MemoryExhausted; - selectedCertificate->read(*selectedSignatureItem); + result = selectedCertificate->read(*selectedSignatureItem); + if (result.bad()) + { + // a failure to read the certificate should not cause a failure + // of the "selectSignature" operation. We actually want the + // signature verification to fail in this case. + DCMSIGN_DEBUG(result.text() << " while reading certificate."); + } + + selectedTimestamp = new SiTimeStampFS(); + if (selectedTimestamp == NULL) return EC_MemoryExhausted; + result = selectedTimestamp->read(*selectedSignatureItem); + if (result.bad() && (result != EC_TagNotFound)) + { + DCMSIGN_WARN(result.text() << " while reading timestamp."); + delete selectedTimestamp; + selectedTimestamp = NULL; + } + return EC_Normal; } @@ -634,7 +729,9 @@ OFCondition DcmSignature::verifyCurrent() { tagList = new DcmAttributeTag(*((DcmAttributeTag *)(stack.top()))); if (tagList == NULL) result = EC_MemoryExhausted; + else if (tagList->getVM() == 0) result = SI_EC_VerificationFailed_NoDataElementsSigned; // DataElementsSigned is present but empty } + else result = SI_EC_VerificationFailed_NoDataElementsSigned; // DataElementsSigned is absent or does not have "AT" VR } // read Signature @@ -651,12 +748,11 @@ OFCondition DcmSignature::verifyCurrent() // create MAC if (result.good()) { - DcmAttributeTag tagListOut(DCM_DataElementsSigned); SiMACConstructor constructor; if (dumpFile) constructor.setDumpFile(dumpFile); // encode main dataset - result = constructor.encodeDataset(*currentItem, *mac, xfer, tagListOut, tagList); + result = constructor.encodeDatasetForVerification(*currentItem, *mac, xfer, tagList); // encode required attributes from the digital signatures sequence if (result.good()) result = constructor.encodeDigitalSignatureItem(*selectedSignatureItem, *mac, xfer); @@ -672,11 +768,19 @@ OFCondition DcmSignature::verifyCurrent() if (algorithm) { OFBool verified = OFTrue; - Uint32 sigLength = signature->getLength(); + unsigned long sigLength = signature->getLength(); Uint8 *sigData = NULL; if ((signature->getUint8Array(sigData)).bad() || (sigData == NULL)) result = SI_EC_VerificationFailed_NoSignature; else { + // check if the digital signature has an odd number of bytes + if (selectedCertificate->getKeyType() == EKT_DSA || selectedCertificate->getKeyType() == EKT_EC) + { + // DSA and ECDSA signatures are encoded in DER and can have odd length. We must remove + // the pad byte before feeding the signature to the OpenSSL layer. + adjustASN1SequenceLength(sigData, sigLength); + } + unsigned long digestLength = mac->getSize(); unsigned char *digest = new unsigned char[digestLength]; if (digest == NULL) result = EC_MemoryExhausted; @@ -695,6 +799,45 @@ OFCondition DcmSignature::verifyCurrent() } else result = SI_EC_VerificationFailed_NoCertificate; } + // check signature date against certificate expiry date + if (result.good()) + { + DcmDateTime *dt = getCurrentSignatureDateTime(); + if (dt) + { + OFDateTime odt; + result = dt->getOFDateTime(odt); + if (result.good()) + { + // convert DICOM datetime string to YYYYMMDDHHMMSSZ format. + // Note that we ignore the timezone here, which not correct + // (we should adjust the datetime for the timezone) + OFString asn1dt; + char buf[40]; + OFStandard::snprintf(buf, 40, "%04u%02u%02u%02u%02u%02uZ", + odt.getDate().getYear(), odt.getDate().getMonth(), odt.getDate().getDay(), + odt.getTime().getHour(), odt.getTime().getMinute(), odt.getTime().getIntSecond()); + asn1dt = buf; + if (selectedCertificate->isCertExpiredAt(asn1dt)) + { + // certificate was already expired at signature date time + result = SI_EC_VerificationFailed_CertExpiredAtSignature; + } + else if (selectedCertificate->isCertNotYetValidAt(asn1dt)) + { + // certificate was not yet valid at signature date time, + // so this is probably a backdated signature + result = SI_EC_VerificationFailed_CertNotYetValidAtSig; + } + } + } + else + { + DCMSIGN_WARN("DigitalSignatureDateTime attribute is invalid"); + result = SI_EC_VerificationFailed_CertExpiredAtSignature; + } + } + delete signature; delete tagList; delete mac; @@ -711,19 +854,46 @@ DcmItem *DcmSignature::findFirstSignatureItem(DcmItem& item, DcmStack& stack) DcmItem *DcmSignature::findNextSignatureItem(DcmItem& item, DcmStack& stack) { - if (item.search(DCM_DigitalSignaturesSequence, stack, ESM_afterStackTop, OFTrue).good()) + do { - DcmObject *nextItem = stack.elem(1); - if (nextItem && ((nextItem->ident() == EVR_item) || (nextItem->ident() == EVR_dataset))) return (DcmItem *)nextItem; - } - return NULL; + if (item.search(DCM_DigitalSignaturesSequence, stack, ESM_afterStackTop, OFTrue).good()) + { + // We have found a DigitalSignaturesSequence. Check if the sequence is + // located within the OriginalAttributesSequence. This would indicate that + // this is an "old" signature that was valid before some update was applied + // to the DICOM object. This signature thus cannot and should not be verified. + // We currently have no code that would "undo" the modifications by moving + // the content of the OriginalAttributesSequence back to its original place + // and then try to verify the signature. For now we only inform the user + // about the situation. + DcmObject *nextItem = NULL; + unsigned long card = stack.card(); + OFBool inOriginalAttributesSequence = OFFalse; + for (unsigned long i=0; igetTag() == DCM_OriginalAttributesSequence) + { + DCMSIGN_WARN("Found Digital Signature Sequence within the Original Attributes Sequence, ignoring."); + inOriginalAttributesSequence = OFTrue; + break; // break out of for loop + } + } + if (inOriginalAttributesSequence) continue; // skip to next iteration of do-while loop + + // we're not in the OriginalAttributesSequence. Return a pointer to the dataset + // or item in which the DigitalSignaturesSequence is contained. + nextItem = stack.elem(1); + if (nextItem && ((nextItem->ident() == EVR_item) || (nextItem->ident() == EVR_dataset))) return (DcmItem *)nextItem; + } + return NULL; // no signature found or invalid VR (i.e. something has gone very wrong) + } while (OFTrue); } OFCondition DcmSignature::getCurrentMacID(Uint16& macID) { if (NULL == selectedSignatureItem) return EC_IllegalCall; - macID = getMACIDnumber(*selectedSignatureItem); - return EC_Normal; + return getMACIDnumber(*selectedSignatureItem, macID); } OFCondition DcmSignature::getCurrentMacXferSyntaxName(OFString& str) @@ -737,7 +907,7 @@ OFCondition DcmSignature::getCurrentMacXferSyntaxName(OFString& str) if ((selectedMacParametersItem->search(DCM_MACCalculationTransferSyntaxUID, stack, ESM_fromHere, OFFalse)).good() && (stack.top()->isLeaf())) { char *uid = NULL; - if ((((DcmElement *)(stack.top()))->getString(uid)).good()) + if ((((DcmElement *)(stack.top()))->getString(uid)).good() && uid) { DcmXfer xf(uid); if (xf.getXfer() == EXS_Unknown) str=uid; else @@ -750,6 +920,27 @@ OFCondition DcmSignature::getCurrentMacXferSyntaxName(OFString& str) return result; } + +OFCondition DcmSignature::getCurrentSignaturePurpose(OFString& codeValue, OFString& codeMeaning, OFString& codingSchemeDesignator) +{ + codeValue.clear(); + codeMeaning.clear(); + codingSchemeDesignator.clear(); + + if ((NULL == selectedSignatureItem)||(NULL == selectedMacParametersItem)) return EC_IllegalCall; + + DcmItem *item = NULL; + OFCondition result = selectedSignatureItem->findAndGetSequenceItem(DCM_DigitalSignaturePurposeCodeSequence, item, 0); + if (result.good()) + { + result = item->findAndGetOFString(DCM_CodeValue, codeValue); + if (result.good()) result = item->findAndGetOFString(DCM_CodeValue, codeValue); + if (result.good()) result = item->findAndGetOFString(DCM_CodeMeaning, codeMeaning); + if (result.good()) result = item->findAndGetOFString(DCM_CodingSchemeDesignator, codingSchemeDesignator); + } + return result; +} + OFCondition DcmSignature::getCurrentMacName(OFString& str) { str.clear(); @@ -780,6 +971,19 @@ OFCondition DcmSignature::getCurrentSignatureUID(OFString& str) return result; } +DcmDateTime *DcmSignature::getCurrentSignatureDateTime() +{ + DcmStack stack; + if (selectedSignatureItem && (selectedSignatureItem->search(DCM_DigitalSignatureDateTime, stack, ESM_fromHere, OFFalse)).good() && (stack.top()->isLeaf())) + { + if (stack.top()->ident() == EVR_DT) + { + return OFreinterpret_cast(DcmDateTime *, stack.top()); + } + } + return NULL; +} + OFCondition DcmSignature::getCurrentSignatureDateTime(OFString& str) { str.clear(); @@ -800,6 +1004,11 @@ SiCertificate *DcmSignature::getCurrentCertificate() return selectedCertificate; } +SiTimeStamp *DcmSignature::getCurrentTimestamp() +{ + return selectedTimestamp; +} + OFCondition DcmSignature::getCurrentDataElementsSigned(DcmAttributeTag& desig) { desig.clear(); @@ -816,6 +1025,140 @@ OFCondition DcmSignature::getCurrentDataElementsSigned(DcmAttributeTag& desig) return result; } +DcmItem *DcmSignature::getSelectedSignatureItem() +{ + return selectedSignatureItem; +} + +void DcmSignature::adjustASN1SequenceLength(const unsigned char *buf, unsigned long& buflen) +{ + // ASN.1 sequence objects encoded in DER can have odd length. Remove the pad byte, if any. + if (((buflen > 2) && buf && (buf[0] == 0x30) && (buf[1] < 128) && (buf[1]+3U == buflen)) || // one-byte length encoding + ((buflen > 4) && buf && (buf[0] == 0x30) && (buf[1] == 0x82) && ((256UL * buf[2]) + buf[3] + 5U == buflen))) // two-byte length encoding + { + // The first byte of the signature is 0x30 (DER encoding for SEQUENCE) + // and length field is one byte shorter than our buffer size. + // Adjust buflen to remove the pad byte. + --buflen; + } +} + + +OFCondition DcmSignature::verifySignatureProfile(SiSecurityProfile &sprof) +{ + if (NULL == currentItem) return EC_IllegalCall; + if (selectedMacParametersItem == NULL) return SI_EC_VerificationFailed_NoMAC; + if ((selectedCertificate == NULL)||(selectedCertificate->getKeyType() == EKT_none)) return SI_EC_VerificationFailed_NoCertificate; + + E_TransferSyntax xfer = EXS_Unknown; + DcmStack stack; + + // check if the profile only applies to main dataset level + if ((currentItem->ident() != EVR_dataset) && sprof.mainDatasetRequired()) + return SI_EC_DatasetDoesNotMatchProfile; + + // let the signature profile handler inspect the dataset first + OFCondition result = sprof.inspectSignatureDataset(*currentItem); + + // check MAC Calculation Transfer Syntax UID + if (result.good()) + { + if ((selectedMacParametersItem->search(DCM_MACCalculationTransferSyntaxUID, stack, ESM_fromHere, OFFalse)).good() && (stack.top()->isLeaf())) + { + char *uid = NULL; + if ((((DcmElement *)(stack.top()))->getString(uid)).good()) + { + DcmXfer xf(uid); + xfer = xf.getXfer(); + if ((xfer == EXS_Unknown) || (! sprof.isAllowableTransferSyntax(xfer))) result = SI_EC_TransferSyntaxDoesNotMatchProfile; + } else result = SI_EC_VerificationFailed_NoMAC; + } else result = SI_EC_VerificationFailed_NoMAC; + } + + // check signature algorithm type + if (result.good()) + { + if (! sprof.isAllowableAlgorithmType(selectedCertificate->getKeyType())) result = SI_EC_AlgorithmDoesNotMatchProfile; + } + + // check MAC Algorithm + if (result.good()) + { + E_MACType mac = EMT_RIPEMD160; + stack.clear(); + if ((selectedMacParametersItem->search(DCM_MACAlgorithm, stack, ESM_fromHere, OFFalse)).good() && (stack.top()->isLeaf())) + { + OFString macidentifier; + if ((((DcmElement *)(stack.top()))->getOFString(macidentifier, 0)).good()) + { + if (macidentifier == SI_DEFTERMS_RIPEMD160) mac = EMT_RIPEMD160; + else if (macidentifier == SI_DEFTERMS_SHA1) mac = EMT_SHA1; + else if (macidentifier == SI_DEFTERMS_MD5) mac = EMT_MD5; + else if (macidentifier == SI_DEFTERMS_SHA256) mac = EMT_SHA256; + else if (macidentifier == SI_DEFTERMS_SHA384) mac = EMT_SHA384; + else if (macidentifier == SI_DEFTERMS_SHA512) mac = EMT_SHA512; + else result = SI_EC_VerificationFailed_UnsupportedMACAlgorithm; + if (result.good() && (! sprof.isAllowableMACType(mac))) result = SI_EC_MacDoesNotMatchProfile; + } else result = SI_EC_VerificationFailed_NoMAC; + } else result = SI_EC_VerificationFailed_NoMAC; + } + + // check list of Data Elements Signed + if (result.good()) + { + stack.clear(); + if ((selectedMacParametersItem->search(DCM_DataElementsSigned, stack, ESM_fromHere, OFFalse)).good() && (stack.top()->ident() == EVR_AT)) + { + DcmAttributeTag *tagList = new DcmAttributeTag(*((DcmAttributeTag *)(stack.top()))); + if (tagList == NULL) result = EC_MemoryExhausted; + else + { + if (! sprof.checkAttributeList(*currentItem, *tagList)) result = SI_EC_DataElementsSignedDoesNotMatchProfile; + } + delete tagList; + } + else result = SI_EC_VerificationFailed_NoDataElementsSigned; // DataElementsSigned is absent or does not have "AT" VR + } + + return result; +} + +OFCondition DcmSignature::checkListOfSignedTags(const DcmAttributeTag *tagList, const DcmAttributeTag *tagListOut) +{ + if (tagListOut == NULL) return EC_IllegalCall; + + OFCondition result = EC_Normal; + if (tagList) + { + DcmAttributeTag tagListNonConst(*tagList); // we need a non-const copy of tagList + DcmTagKey key; + unsigned long vm = tagListNonConst.getVM(); + for (unsigned long i=0; i < vm; i++) + { + if ((tagListNonConst.getTagVal(key, i)).good() && (! inTagList(key, *tagListOut))) + { + result = EC_TagNotFound; + DCMSIGN_ERROR("attribute " << key << " should be signed but is not present in the dataset."); + } + } + } + return result; +} + +OFBool DcmSignature::inTagList(const DcmTagKey &tag, const DcmAttributeTag& tagList) +{ + DcmTagKey key; + DcmAttributeTag tagListNonConst(tagList); // we need a non-const copy of tagList + unsigned long vm = tagListNonConst.getVM(); + for (unsigned long i=0; i < vm; i++) + { + if ((tagListNonConst.getTagVal(key, i)).good() && (key == tag)) return OFTrue; + } + return OFFalse; +} + + + #else /* WITH_OPENSSL */ #include "dcmtk/dcmsign/sidefine.h" diff --git a/dcmsign/libsrc/siautopr.cc b/dcmsign/libsrc/siautopr.cc index e5ec78f1..16100b3a 100644 --- a/dcmsign/libsrc/siautopr.cc +++ b/dcmsign/libsrc/siautopr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2010, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -26,50 +26,648 @@ #include "dcmtk/dcmsign/siautopr.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmsign/sitypes.h" -OFBool SiAuthorizationProfile::attributeRequired(const DcmTagKey& key) const +SiAuthorizationProfile::SiAuthorizationProfile() +: containsRawData_(OFFalse) { - /* SOP Class and Instance UIDs */ +} + +OFBool SiAuthorizationProfile::attributeRequiredIfPresent(const DcmTagKey& key) const +{ + // The Authorization RSA Digital Signature Profile requires that any + // attributes whose Values are verifiable by the technician or physician + // (e.g., their values are displayed to the technician or physician) must + // be included in the signature. This must be handled manually. + + // the SOP Class and Instance UIDs if (key == DCM_SOPClassUID) return OFTrue; if (key == DCM_SOPInstanceUID) return OFTrue; - /* Study and Series Instance UIDs */ + // the Study and Series Instance UIDs if (key == DCM_StudyInstanceUID) return OFTrue; if (key == DCM_SeriesInstanceUID) return OFTrue; - - /* Any overlay data present */ - if ((key.getGroup() >= 0x6000) && (key.getGroup() < 0x6020) && ((key.getGroup() & 0x0001) == 0)) return OFTrue; - - /* Any image data present - we assume this means the Image Pixel Module and not just PixelData */ - if (key.getGroup() == 0x0028) + + // any attributes of the Overlay Plane Module that are present + if (key == DCM_OverlayRows) return OFTrue; + if (key == DCM_OverlayColumns) return OFTrue; + if (key == DCM_OverlayType) return OFTrue; + if (key == DCM_OverlayOrigin) return OFTrue; + if (key == DCM_OverlayBitsAllocated) return OFTrue; + if (key == DCM_OverlayBitPosition) return OFTrue; + if (key == DCM_OverlayData) return OFTrue; + if (key == DCM_OverlayDescription) return OFTrue; + if (key == DCM_OverlaySubtype) return OFTrue; + if (key == DCM_OverlayLabel) return OFTrue; + if (key == DCM_ROIArea) return OFTrue; + if (key == DCM_ROIMean) return OFTrue; + if (key == DCM_ROIStandardDeviation) return OFTrue; + + // any attributes of the Curve Module that are present + if ((key.getGroup() >= 0x5000) && (key.getGroup() < 0x5020) && ((key.getGroup() & 1) == 0)) { - Uint16 elem = key.getElement(); - if (elem == 0x0002) return OFTrue; // DCM_SamplesPerPixel - if (elem == 0x0004) return OFTrue; // DCM_PhotometricInterpretation - if (elem == 0x0006) return OFTrue; // DCM_PlanarConfiguration - if (elem == 0x0010) return OFTrue; // DCM_Rows - if (elem == 0x0011) return OFTrue; // DCM_Columns - if (elem == 0x0034) return OFTrue; // DCM_PixelAspectRatio - if (elem == 0x0100) return OFTrue; // DCM_BitsAllocated - if (elem == 0x0101) return OFTrue; // DCM_BitsStored - if (elem == 0x0102) return OFTrue; // DCM_HighBit - if (elem == 0x0103) return OFTrue; // DCM_PixelRepresentation - if (elem == 0x0106) return OFTrue; // DCM_SmallestImagePixelValue - if (elem == 0x0107) return OFTrue; // DCM_LargestImagePixelValue - if (elem == 0x1101) return OFTrue; // DCM_RedPaletteColorLookupTableDescriptor - if (elem == 0x1102) return OFTrue; // DCM_GreenPaletteColorLookupTableDescriptor - if (elem == 0x1103) return OFTrue; // DCM_BluePaletteColorLookupTableDescriptor - if (elem == 0x1201) return OFTrue; // DCM_RedPaletteColorLookupTableData - if (elem == 0x1202) return OFTrue; // DCM_GreenPaletteColorLookupTableData - if (elem == 0x1203) return OFTrue; // DCM_BluePaletteColorLookupTableData + switch (key.getElement()) + { + case 0x0005: // CurveDimensions (retired) + case 0x0010: // NumberOfPoints (retired) + case 0x0103: // DataValueRepresentation (retired) + case 0x3000: // CurveData (retired) + case 0x0022: // CurveDescription (retired) + case 0x0030: // AxisUnits (retired) + case 0x0040: // AxisLabels (retired) + case 0x0104: // MinimumCoordinateValue (retired) + case 0x0105: // MaximumCoordinateValue (retired) + case 0x0106: // CurveRange (retired) + case 0x0110: // CurveDataDescriptor (retired) + case 0x0112: // CoordinateStartValue (retired) + case 0x0114: // CoordinateStepValue (retired) + case 0x2500: // CurveLabel (retired) + case 0x2600: // ReferencedOverlaySequence (retired) + return OFTrue; + break; + default: + /* nothing */ + break; + } } + + // any attributes of the Graphic Annotation Module that are present + if (key == DCM_GraphicAnnotationSequence) return OFTrue; + + // any attributes of the General Image Module that are present + if (key == DCM_InstanceNumber) return OFTrue; + if (key == DCM_PatientOrientation) return OFTrue; + if (key == DCM_ContentDate) return OFTrue; + if (key == DCM_ContentTime) return OFTrue; + if (key == DCM_ImageType) return OFTrue; + if (key == DCM_AcquisitionNumber) return OFTrue; + if (key == DCM_AcquisitionDate) return OFTrue; + if (key == DCM_AcquisitionTime) return OFTrue; + if (key == DCM_AcquisitionDateTime) return OFTrue; + if (key == DCM_ImagesInAcquisition) return OFTrue; + if (key == DCM_ImageComments) return OFTrue; + if (key == DCM_QualityControlImage) return OFTrue; + if (key == DCM_BurnedInAnnotation) return OFTrue; + if (key == DCM_RecognizableVisualFeatures) return OFTrue; + if (key == DCM_LossyImageCompression) return OFTrue; + if (key == DCM_LossyImageCompressionRatio) return OFTrue; + if (key == DCM_LossyImageCompressionMethod) return OFTrue; + if (key == DCM_IconImageSequence) return OFTrue; + if (key == DCM_PresentationLUTShape) return OFTrue; + if (key == DCM_IrradiationEventUID) return OFTrue; + if (key == DCM_RealWorldValueMappingSequence) return OFTrue; + if (key == DCM_ImageLaterality) return OFTrue; + if (key == DCM_AnatomicRegionSequence) return OFTrue; + if (key == DCM_PrimaryAnatomicStructureSequence) return OFTrue; + + // any attributes of the Image Pixel Module that are present + if (key == DCM_SamplesPerPixel) return OFTrue; + if (key == DCM_PhotometricInterpretation) return OFTrue; + if (key == DCM_Rows) return OFTrue; + if (key == DCM_Columns) return OFTrue; + if (key == DCM_BitsAllocated) return OFTrue; + if (key == DCM_BitsStored) return OFTrue; + if (key == DCM_HighBit) return OFTrue; + if (key == DCM_PixelRepresentation) return OFTrue; + if (key == DCM_PlanarConfiguration) return OFTrue; + if (key == DCM_PixelAspectRatio) return OFTrue; + if (key == DCM_SmallestImagePixelValue) return OFTrue; + if (key == DCM_LargestImagePixelValue) return OFTrue; + if (key == DCM_RedPaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_GreenPaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_BluePaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_RedPaletteColorLookupTableData) return OFTrue; + if (key == DCM_GreenPaletteColorLookupTableData) return OFTrue; + if (key == DCM_BluePaletteColorLookupTableData) return OFTrue; + if (key == DCM_ICCProfile) return OFTrue; + if (key == DCM_ColorSpace) return OFTrue; if (key == DCM_PixelData) return OFTrue; + if (key == DCM_PixelDataProviderURL) return OFTrue; + if (key == DCM_PixelPaddingRangeLimit) return OFTrue; + if (key == DCM_ExtendedOffsetTable) return OFTrue; + if (key == DCM_ExtendedOffsetTableLengths) return OFTrue; + + // any attributes of the SR Document General Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + if (key == DCM_PreliminaryFlag) return OFTrue; + if (key == DCM_CompletionFlag) return OFTrue; + if (key == DCM_CompletionFlagDescription) return OFTrue; + if (key == DCM_VerificationFlag) return OFTrue; + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + if (key == DCM_VerifyingObserverSequence) return OFTrue; + if (key == DCM_AuthorObserverSequence) return OFTrue; + if (key == DCM_ParticipantSequence) return OFTrue; + if (key == DCM_CustodialOrganizationSequence) return OFTrue; + if (key == DCM_PredecessorDocumentsSequence) return OFTrue; + if (key == DCM_IdenticalDocumentsSequence) return OFTrue; + if (key == DCM_ReferencedRequestSequence) return OFTrue; + if (key == DCM_PerformedProcedureCodeSequence) return OFTrue; + if (key == DCM_CurrentRequestedProcedureEvidenceSequence) return OFTrue; + if (key == DCM_PertinentOtherEvidenceSequence) return OFTrue; + if (key == DCM_ReferencedInstanceSequence) return OFTrue; + + // any attributes of the SR Document Content Module that are present + if (key == DCM_ValueType) return OFTrue; + if (key == DCM_ConceptNameCodeSequence) return OFTrue; + if (key == DCM_ContinuityOfContent) return OFTrue; + if (key == DCM_ContentTemplateSequence) return OFTrue; + if (key == DCM_ObservationDateTime) return OFTrue; + if (key == DCM_ObservationUID) return OFTrue; + if (key == DCM_ContentSequence) return OFTrue; + + // any attributes of the Waveform Module that are present + if (key == DCM_WaveformSequence) return OFTrue; + if (key == DCM_WaveformDataDisplayScale) return OFTrue; + if (key == DCM_WaveformDisplayBackgroundCIELabValue) return OFTrue; + if (key == DCM_WaveformPresentationGroupSequence) return OFTrue; + + // any attributes of the Waveform Annotation Module that are present + if (key == DCM_WaveformAnnotationSequence) return OFTrue; + + // any attributes of the Multi-frame Functional Groups module that are present + if (key == DCM_SharedFunctionalGroupsSequence) return OFTrue; + if (key == DCM_PerFrameFunctionalGroupsSequence) return OFTrue; + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + if (key == DCM_NumberOfFrames) return OFTrue; + if (key == DCM_StereoPairsPresent) return OFTrue; + if (key == DCM_ConcatenationFrameOffsetNumber) return OFTrue; + if (key == DCM_RepresentativeFrameNumber) return OFTrue; + if (key == DCM_ConcatenationUID) return OFTrue; + if (key == DCM_SOPInstanceUIDOfConcatenationSource) return OFTrue; + if (key == DCM_InConcatenationNumber) return OFTrue; + if (key == DCM_InConcatenationTotalNumber) return OFTrue; + + // any attributes of the Enhanced MR Image Module that are present + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + if (key == DCM_AcquisitionDuration) return OFTrue; + if (key == DCM_ReferencedRawDataSequence) return OFTrue; + if (key == DCM_ReferencedWaveformSequence) return OFTrue; + if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; + if (key == DCM_SourceImageEvidenceSequence) return OFTrue; + if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; + if (key == DCM_ContentQualification) return OFTrue; + if (key == DCM_ResonantNucleus) return OFTrue; + if (key == DCM_KSpaceFiltering) return OFTrue; + if (key == DCM_MagneticFieldStrength) return OFTrue; + if (key == DCM_ApplicableSafetyStandardAgency) return OFTrue; + if (key == DCM_ApplicableSafetyStandardDescription) return OFTrue; + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + if (key == DCM_IsocenterPosition) return OFTrue; + if (key == DCM_B1rms) return OFTrue; + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_PixelPresentation) return OFTrue; + if (key == DCM_VolumetricProperties) return OFTrue; + if (key == DCM_VolumeBasedCalculationTechnique) return OFTrue; + if (key == DCM_ComplexImageComponent) return OFTrue; + if (key == DCM_AcquisitionContrast) return OFTrue; + if (key == DCM_FunctionalSettlingPhaseFramesPresent) return OFTrue; + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PlanarConfiguration) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_ViewCodeSequence) return OFTrue; + if (key == DCM_SliceProgressionDirection) return OFTrue; + + // any attributes of the MR Spectroscopy modules that are present + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ResonantNucleus) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_k-SpaceFiltering) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_MagneticFieldStrength) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ApplicableSafetyStandardAgency) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ApplicableSafetyStandardDescription) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_IsocenterPosition) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_B1rms) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageType) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_VolumetricProperties) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_VolumeBasedCalculationTechnique) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ComplexImageComponent) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionContrast) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_TransmitterFrequency) return OFTrue; + if (key == DCM_SpectralWidth) return OFTrue; + if (key == DCM_ChemicalShiftReference) return OFTrue; + if (key == DCM_VolumeLocalizationTechnique) return OFTrue; + if (key == DCM_VolumeLocalizationSequence) return OFTrue; + if (key == DCM_Decoupling) return OFTrue; + if (key == DCM_DecoupledNucleus) return OFTrue; + if (key == DCM_DecouplingFrequency) return OFTrue; + if (key == DCM_DecouplingMethod) return OFTrue; + if (key == DCM_DecouplingChemicalShiftReference) return OFTrue; + if (key == DCM_TimeDomainFiltering) return OFTrue; + if (key == DCM_NumberOfZeroFills) return OFTrue; + if (key == DCM_BaselineCorrection) return OFTrue; + if (key == DCM_FrequencyCorrection) return OFTrue; + if (key == DCM_FirstOrderPhaseCorrection) return OFTrue; + if (key == DCM_WaterReferencedPhaseCorrection) return OFTrue; + if (key == DCM_WaterReferenceAcquisition) return OFTrue; + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + + // any attributes of the Raw Data module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + if (key == DCM_ContentLabel) return OFTrue; + if (key == DCM_ContentDescription) return OFTrue; + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ImageLaterality) return OFTrue; // also in General Image Module + if (key == DCM_CreatorVersionUID) return OFTrue; + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + + // if the Raw Data Module is present, we need to include all private tags into + // signature because the raw data as such is stored in private attributes. + if (((key.getGroup() & 1) == 1) && containsRawData_) return OFTrue; + + // any attributes of the Enhanced CT Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_MultienergyCTAcquisition) return OFTrue; + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_IsocenterPosition) return OFTrue; // also in Enhanced MR Image Module + + // any attributes of the Enhanced XA/XRF Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_PlanesInAcquisition) return OFTrue; + if (key == DCM_PlaneIdentification) return OFTrue; + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + if (key == DCM_AcquisitionProtocolName) return OFTrue; + if (key == DCM_AcquisitionProtocolDescription) return OFTrue; + if (key == DCM_ScanOptions) return OFTrue; + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_PatientOrientationCodeSequence) return OFTrue; // also in General Image Module + if (key == DCM_PatientGantryRelationshipCodeSequence) return OFTrue; + if (key == DCM_ExaminedBodyThickness) return OFTrue; + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_ReferencedOtherPlaneSequence) return OFTrue; + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + + // any attributes of the Segmentation Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_ImageOrientationSlide) return OFTrue; + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_SegmentationType) return OFTrue; + if (key == DCM_SegmentationFractionalType) return OFTrue; + if (key == DCM_MaximumFractionalValue) return OFTrue; + if (key == DCM_SegmentsOverlap) return OFTrue; + if (key == DCM_SegmentSequence) return OFTrue; + + // any attributes of the Encapsulated Document module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_ImageLaterality) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + if (key == DCM_SourceInstanceSequence) return OFTrue; + if (key == DCM_DocumentTitle) return OFTrue; + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + if (key == DCM_DocumentClassCodeSequence) return OFTrue; + // if (key == DCM_VerificationFlag) return OFTrue; // also in SR Document General Module + if (key == DCM_HL7InstanceIdentifier) return OFTrue; + // if (key == DCM_PredecessorDocumentsSequence) return OFTrue; // also in SR Document General Module + // if (key == DCM_IdenticalDocumentsSequence) return OFTrue; // also in SR Document General Module + if (key == DCM_MIMETypeOfEncapsulatedDocument) return OFTrue; + if (key == DCM_ListOfMIMETypes) return OFTrue; + if (key == DCM_EncapsulatedDocument) return OFTrue; + if (key == DCM_EncapsulatedDocumentLength) return OFTrue; + // if (key == DCM_ValueType) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContentSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContinuityOfContent) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContentTemplateSequence) return OFTrue; // also in SR Document Content Module + + // any attributes of the X-Ray 3D Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + if (key == DCM_SourceIrradiationEventSequence) return OFTrue; + + // any attributes of the Enhanced PET Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + + // any attributes of the Enhanced US Image module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + if (key == DCM_DimensionOrganizationType) return OFTrue; + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_PositionMeasuringDeviceUsed) return OFTrue; + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + if (key == DCM_RescaleIntercept) return OFTrue; + if (key == DCM_RescaleSlope) return OFTrue; + if (key == DCM_SourceImageSequence) return OFTrue; + if (key == DCM_ReferencedImageSequence) return OFTrue; + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + if (key == DCM_NumberOfStages) return OFTrue; + if (key == DCM_StageNumber) return OFTrue; + if (key == DCM_StageCodeSequence) return OFTrue; + if (key == DCM_EventTimerSequence) return OFTrue; + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_TransducerData) return OFTrue; + if (key == DCM_TransducerGeometryCodeSequence) return OFTrue; + if (key == DCM_TransducerBeamSteeringCodeSequence) return OFTrue; + if (key == DCM_TransducerApplicationCodeSequence) return OFTrue; + if (key == DCM_ProcessingFunction) return OFTrue; + if (key == DCM_MechanicalIndex) return OFTrue; + if (key == DCM_BoneThermalIndex) return OFTrue; + if (key == DCM_CranialThermalIndex) return OFTrue; + if (key == DCM_SoftTissueThermalIndex) return OFTrue; + if (key == DCM_DepthsOfFocus) return OFTrue; + if (key == DCM_DepthOfScanField) return OFTrue; + + // any attributes of the Surface Segmentation module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentLabel) return OFTrue; // also in Raw Data Module + // if (key == DCM_ContentDescription) return OFTrue; // also in Raw Data Module + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + if (key == DCM_AlternateContentDescriptionSequence) return OFTrue; + if (key == DCM_ContentCreatorName) return OFTrue; + if (key == DCM_ContentCreatorIdentificationCodeSequence) return OFTrue; + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_SegmentSequence) return OFTrue; // also in Segmentation Image Module - /* Any attributes whose values are verifiable by the technician or physician + // any attributes of the Surface Mesh Module that are present + if (key == DCM_NumberOfSurfaces) return OFTrue; + if (key == DCM_SurfaceSequence) return OFTrue; + + // any attributes of the Structured Display module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentLabel) return OFTrue; // also in Raw Data Module + // if (key == DCM_ContentDescription) return OFTrue; // also in Raw Data Module + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_AlternateContentDescriptionSequence) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorName) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorIdentificationCodeSequence) return OFTrue; // also in Surface Segmentation Module + if (key == DCM_PresentationCreationDate) return OFTrue; + if (key == DCM_PresentationCreationTime) return OFTrue; + if (key == DCM_NumberOfScreens) return OFTrue; + if (key == DCM_NominalScreenDefinitionSequence) return OFTrue; + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_StructuredDisplayBackgroundCIELabValue) return OFTrue; + if (key == DCM_EmptyImageBoxCIELabValue) return OFTrue; + if (key == DCM_HangingProtocolName) return OFTrue; + if (key == DCM_HangingProtocolCreator) return OFTrue; + + // any attributes of the Structured Display Annotation module that are present + if (key == DCM_StructuredDisplayTextBoxSequence) return OFTrue; + + // any attributes of the Structured Display Image Box module that are present + if (key == DCM_StructuredDisplayImageBoxSequence) return OFTrue; + if (key == DCM_ImageBoxSynchronizationSequence) return OFTrue; + + // any Attributes of the Implant Template module that are present + if (key == DCM_Manufacturer) return OFTrue; + if (key == DCM_FrameOfReferenceUID) return OFTrue; + if (key == DCM_ImplantName) return OFTrue; + if (key == DCM_ImplantSize) return OFTrue; + if (key == DCM_ImplantPartNumber) return OFTrue; + if (key == DCM_ImplantTemplateVersion) return OFTrue; + if (key == DCM_ReplacedImplantTemplateSequence) return OFTrue; + if (key == DCM_ImplantType) return OFTrue; + if (key == DCM_OriginalImplantTemplateSequence) return OFTrue; + if (key == DCM_DerivationImplantTemplateSequence) return OFTrue; + if (key == DCM_EffectiveDateTime) return OFTrue; + if (key == DCM_ImplantTargetAnatomySequence) return OFTrue; + if (key == DCM_NotificationFromManufacturerSequence) return OFTrue; + if (key == DCM_InformationFromManufacturerSequence) return OFTrue; + if (key == DCM_ImplantRegulatoryDisapprovalCodeSequence) return OFTrue; + if (key == DCM_OverallTemplateSpatialTolerance) return OFTrue; + if (key == DCM_MaterialsCodeSequence) return OFTrue; + if (key == DCM_CoatingMaterialsCodeSequence) return OFTrue; + if (key == DCM_ImplantTypeCodeSequence) return OFTrue; + if (key == DCM_FixationMethodCodeSequence) return OFTrue; + + // any Attributes of the Implant Assembly Template module that are present + // if (key == DCM_EffectiveDateTime) return OFTrue; // also in Implant Template Module + if (key == DCM_ImplantAssemblyTemplateName) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateIssuer) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateVersion) return OFTrue; + if (key == DCM_ReplacedImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateType) return OFTrue; + if (key == DCM_OriginalImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_DerivationImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateTargetAnatomySequence) return OFTrue; + if (key == DCM_ProcedureTypeCodeSequence) return OFTrue; + if (key == DCM_SurgicalTechnique) return OFTrue; + // if (key == DCM_MIMETypeOfEncapsulatedDocument) return OFTrue; // also in Encapsulated Document Module + // if (key == DCM_EncapsulatedDocument) return OFTrue; // also in Encapsulated Document Module + if (key == DCM_ComponentTypesSequence) return OFTrue; + if (key == DCM_ComponentAssemblySequence) return OFTrue; + + // any Attributes of the Implant Template Group module that are present + // if (key == DCM_EffectiveDateTime) return OFTrue; // also in Implant Template Module + if (key == DCM_ImplantTemplateGroupName) return OFTrue; + if (key == DCM_ImplantTemplateGroupDescription) return OFTrue; + if (key == DCM_ImplantTemplateGroupIssuer) return OFTrue; + if (key == DCM_ImplantTemplateGroupVersion) return OFTrue; + if (key == DCM_ReplacedImplantTemplateGroupSequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupTargetAnatomySequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupMembersSequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupVariationDimensionSequence) return OFTrue; + + // any attributes of the Point Cloud Module that are present + if (key == DCM_SurfacePointsSequence) return OFTrue; + if (key == DCM_SurfacePointPresentationValueData) return OFTrue; + if (key == DCM_SurfacePointColorCIELabValueData) return OFTrue; + + // any attributes of the Enhanced Mammography Image module that are present + if (key == DCM_PositionerMotion) return OFTrue; + if (key == DCM_PositionerType) return OFTrue; + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_KVP) return OFTrue; + if (key == DCM_XRayTubeCurrentInmA) return OFTrue; + if (key == DCM_ExposureTimeInms) return OFTrue; + if (key == DCM_ExposureInmAs) return OFTrue; + if (key == DCM_FocalSpots) return OFTrue; + if (key == DCM_AnodeTargetMaterial) return OFTrue; + if (key == DCM_BodyPartThickness) return OFTrue; + if (key == DCM_CompressionForce) return OFTrue; + if (key == DCM_CompressionPressure) return OFTrue; + if (key == DCM_CompressionContactArea) return OFTrue; + if (key == DCM_PaddleDescription) return OFTrue; + if (key == DCM_ExposureControlMode) return OFTrue; + if (key == DCM_ExposureControlModeDescription) return OFTrue; + if (key == DCM_PatientOrientation) return OFTrue; + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_OrganDose) return OFTrue; + if (key == DCM_EntranceDoseInmGy) return OFTrue; + if (key == DCM_EntranceDoseDerivation) return OFTrue; + if (key == DCM_TypeOfDetectorMotion) return OFTrue; + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + + // any attributes of the Volumetric Graphic Annotation Module that are present + if (key == DCM_VolumetricAnnotationSequence) return OFTrue; + if (key == DCM_VolumetricPresentationInputAnnotationSequence) return OFTrue; + + /* Any attributes whose values are verifiable by the technician or physician * (e.g., their values are displayed to the technician or physician) * This is obviously application dependent. We don't handle that here. - */ - return OFFalse; + */ + return OFFalse; +} + + +OFBool SiAuthorizationProfile::checkRequiredAttributeList(DcmAttributeTag& tagList) const +{ + OFBool result = + containsTag(tagList, DCM_SOPClassUID) && + containsTag(tagList, DCM_StudyInstanceUID) && + containsTag(tagList, DCM_SeriesInstanceUID) && + containsTag(tagList, DCM_SOPInstanceUID); + + return result; +} + + +OFCondition SiAuthorizationProfile::inspectSignatureDataset(DcmItem &item) +{ + DcmElement *delem = NULL; + if (item.findAndGetElement(DCM_CreatorVersionUID, delem).good()) + { + // The CreatorVersionUID attribute is present in the dataset or item. + // Since this attribute only occurs in the Raw Data Module, this means that + // the Raw Data Module is present. + containsRawData_ = OFTrue; + } + else + { + containsRawData_ = OFFalse; + } + return EC_Normal; +} + +OFBool SiAuthorizationProfile::mainDatasetRequired() const +{ + return OFTrue; } #else /* WITH_OPENSSL */ diff --git a/dcmsign/libsrc/sibrsapr.cc b/dcmsign/libsrc/sibrsapr.cc index 073e45bb..50c03f60 100644 --- a/dcmsign/libsrc/sibrsapr.cc +++ b/dcmsign/libsrc/sibrsapr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2010, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -35,8 +35,13 @@ OFBool SiBaseRSAProfile::isAllowableMACType(E_MACType macType) const case EMT_RIPEMD160: case EMT_SHA1: case EMT_MD5: + // support for the SHA2 hash algorithms was added in DICOM CP 1059. + case EMT_SHA256: + case EMT_SHA384: + case EMT_SHA512: result = OFTrue; break; + default: /* nothing */ break; @@ -59,11 +64,16 @@ OFBool SiBaseRSAProfile::isAllowableAlgorithmType(E_KeyType keyType) const return result; } -OFBool SiBaseRSAProfile::attributeRequired(const DcmTagKey& /* key */) const +OFBool SiBaseRSAProfile::attributeRequiredIfPresent(const DcmTagKey& /* key */) const { return OFFalse; } +OFBool SiBaseRSAProfile::checkRequiredAttributeList(DcmAttributeTag& /* tagList */) const +{ + return OFTrue; +} + OFBool SiBaseRSAProfile::attributeForbidden(const DcmTagKey& /* key */) const { return OFFalse; @@ -75,6 +85,16 @@ OFBool SiBaseRSAProfile::isAllowableTransferSyntax(E_TransferSyntax xfer) const return OFTrue; } +OFCondition SiBaseRSAProfile::inspectSignatureDataset(DcmItem & /* item */) +{ + return EC_Normal; +} + +OFBool SiBaseRSAProfile::mainDatasetRequired() const +{ + return OFFalse; +} + #else /* WITH_OPENSSL */ int sibrsapr_cc_dummy_to_keep_linker_from_moaning = 0; diff --git a/dcmsign/libsrc/sicert.cc b/dcmsign/libsrc/sicert.cc index ea025fcd..9ea05d5d 100644 --- a/dcmsign/libsrc/sicert.cc +++ b/dcmsign/libsrc/sicert.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2016, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,30 +27,41 @@ #include "dcmtk/dcmsign/sicert.h" #include "dcmtk/dcmsign/sirsa.h" /* for class SiRSA */ #include "dcmtk/dcmsign/sidsa.h" /* for class SiDSA */ +#include "dcmtk/dcmsign/siecdsa.h" /* for class SiECDSA */ #include "dcmtk/dcmdata/dcstack.h" #include "dcmtk/dcmdata/dcitem.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/ofstd/ofdatime.h" BEGIN_EXTERN_C #include #include #include +#include END_EXTERN_C -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +#define X509_get0_notBefore(x) X509_get_notBefore(x) +#define X509_get0_notAfter(x) X509_get_notAfter(x) #define EVP_PKEY_id(key) key->type #endif + SiCertificate::SiCertificate() : x509(NULL) { } +SiCertificate::SiCertificate(X509 *cert) +: x509(cert) +{ +} + SiCertificate::~SiCertificate() { - if (x509) X509_free(x509); + if (x509) X509_free(x509); } E_KeyType SiCertificate::getKeyType() @@ -61,7 +72,7 @@ E_KeyType SiCertificate::getKeyType() EVP_PKEY *pkey = X509_extract_key(x509); if (pkey) { - switch(EVP_PKEY_id(pkey)) + switch(EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: result = EKT_RSA; @@ -72,46 +83,57 @@ E_KeyType SiCertificate::getKeyType() case EVP_PKEY_DH: result = EKT_DH; break; + case EVP_PKEY_EC: + result = EKT_EC; + break; default: /* nothing */ break; } EVP_PKEY_free(pkey); - } + } } return result; } SiAlgorithm *SiCertificate::createAlgorithmForPublicKey() { + SiAlgorithm *result = NULL; if (x509) { EVP_PKEY *pkey = X509_extract_key(x509); if (pkey) { - switch(EVP_PKEY_id(pkey)) + switch(EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: - return new SiRSA(EVP_PKEY_get1_RSA(pkey)); - /* break; */ + result = new SiRSA(EVP_PKEY_get1_RSA(pkey)); + break; case EVP_PKEY_DSA: - return new SiDSA(EVP_PKEY_get1_DSA(pkey)); - /* break; */ + result = new SiDSA(EVP_PKEY_get1_DSA(pkey)); + break; + case EVP_PKEY_EC: +#ifdef OPENSSL_NO_EC + result = new SiECDSA(NULL); +#else + result = new SiECDSA(EVP_PKEY_get1_EC_KEY(pkey)); +#endif + break; case EVP_PKEY_DH: default: /* nothing */ break; } EVP_PKEY_free(pkey); - } + } } - return NULL; + return result; } OFCondition SiCertificate::loadCertificate(const char *filename, int filetype) { - OFCondition result = SI_EC_CannotRead; - if (x509) X509_free(x509); + OFCondition result = SI_EC_CannotRead; + if (x509) X509_free(x509); x509 = NULL; if (filename) { @@ -139,6 +161,8 @@ OFCondition SiCertificate::loadCertificate(const char *filename, int filetype) OFCondition SiCertificate::read(DcmItem& item) { OFCondition result = EC_Normal; + if (x509) X509_free(x509); + x509 = NULL; OFString aString; DcmStack stack; result = item.search(DCM_CertificateType, stack, ESM_fromHere, OFFalse); @@ -149,8 +173,8 @@ OFCondition SiCertificate::read(DcmItem& item) { if (aString == SI_DEFTERMS_X509CERT) { - stack.clear(); - result = item.search(DCM_CertificateOfSigner, stack, ESM_fromHere, OFFalse); + stack.clear(); + result = item.search(DCM_CertificateOfSigner, stack, ESM_fromHere, OFFalse); if (result.good()) { DcmElement *cert = (DcmElement *)stack.top(); @@ -167,13 +191,35 @@ OFCondition SiCertificate::read(DcmItem& item) #else x509 = d2i_X509(NULL, &data, cert->getLength()); #endif - if (x509 == NULL) result = EC_IllegalCall; - } else result = EC_IllegalCall; - } - } - } else result = EC_IllegalCall; + if (x509 == NULL) + { + DCMSIGN_WARN("Unable to parse X.509 certificate."); + result = SI_EC_VerificationFailed_NoCertificate; + } + } + else + { + DCMSIGN_WARN("Empty certificate of signer."); + result = SI_EC_VerificationFailed_NoCertificate; + } + } + } + else + { + DCMSIGN_WARN("Certificate missing in dataset."); + result = SI_EC_VerificationFailed_NoCertificate; + } + } else { + DCMSIGN_WARN("Encountered unsupported certificate type '" << aString << "' (expected '" << SI_DEFTERMS_X509CERT << "')."); + result = SI_EC_VerificationFailed_NoCertificate; + } } } + else + { + DCMSIGN_WARN("Certificate type missing in dataset."); + result = SI_EC_VerificationFailed_NoCertificate; + } return result; } @@ -259,7 +305,7 @@ void SiCertificate::getCertValidityNotBefore(OFString& str) BIO *certValidNotBeforeBIO = BIO_new(BIO_s_mem()); if (certValidNotBeforeBIO) { - ASN1_UTCTIME_print(certValidNotBeforeBIO, X509_get_notBefore(x509)); + ASN1_UTCTIME_print(certValidNotBeforeBIO, X509_get0_notBefore(x509)); BIO_write(certValidNotBeforeBIO,"\0",1); BIO_get_mem_data(certValidNotBeforeBIO, (char *)(&bufptr)); if (bufptr) str = bufptr; @@ -277,7 +323,7 @@ void SiCertificate::getCertValidityNotAfter(OFString& str) BIO *certValidNotAfterBIO = BIO_new(BIO_s_mem()); if (certValidNotAfterBIO) { - ASN1_UTCTIME_print(certValidNotAfterBIO, X509_get_notAfter(x509)); + ASN1_UTCTIME_print(certValidNotAfterBIO, X509_get0_notAfter(x509)); BIO_write(certValidNotAfterBIO,"\0",1); BIO_get_mem_data(certValidNotAfterBIO, (char *)(&bufptr)); if (bufptr) str = bufptr; @@ -286,6 +332,91 @@ void SiCertificate::getCertValidityNotAfter(OFString& str) } } +OFBool SiCertificate::isCertExpiredAt(OFString& date) +{ + OFBool result = OFTrue; + if (x509) + { + const ASN1_TIME *certexpiry = X509_get0_notAfter(x509); + OFDateTime dt_certexpiry; + if (certexpiry && convertASN1Time(certexpiry, dt_certexpiry).good()) + { + ASN1_TIME *sigdate = ASN1_TIME_new(); // ASN1_TIME is a typedef for ASN1_STRING + if (sigdate) + { + OFDateTime dt_sigdate; + if (ASN1_TIME_set_string(sigdate, date.c_str()) && convertASN1Time(sigdate, dt_sigdate).good()) + { + // check if signature date is before certificate expiry + if (dt_sigdate < dt_certexpiry) result = OFFalse; + } + ASN1_TIME_free(sigdate); + } + } + } + return result; +} + +OFBool SiCertificate::isCertNotYetValidAt(OFString& date) +{ + OFBool result = OFTrue; + if (x509) + { + const ASN1_TIME *certstart = X509_get0_notBefore(x509); + OFDateTime dt_certstart; + if (certstart && convertASN1Time(certstart, dt_certstart).good()) + { + ASN1_TIME *sigdate = ASN1_TIME_new(); // ASN1_TIME is a typedef for ASN1_STRING + if (sigdate) + { + OFDateTime dt_sigdate; + if (ASN1_TIME_set_string(sigdate, date.c_str()) && convertASN1Time(sigdate, dt_sigdate).good()) + { + // check if signature date is after certificate validity start + if (dt_sigdate > dt_certstart) result = OFFalse; + } + ASN1_TIME_free(sigdate); + } + } + } + return result; +} + + +OFBool SiCertificate::isCertExpiredNow() const +{ + OFBool result = OFTrue; + if (x509) + { + const ASN1_TIME *certexpiry = X509_get0_notAfter(x509); + if (certexpiry) + { + // X509_cmp_current_time() will return -1 when certexpiry is in the past + // and zero if there is an error. In both cases we treat the certificate as expired. + if (X509_cmp_current_time(certexpiry) > 0) result = OFFalse; + } + } + return result; +} + + +OFBool SiCertificate::isCertNotYetValidNow() const +{ + OFBool result = OFTrue; + if (x509) + { + const ASN1_TIME *certstart = X509_get0_notBefore(x509); + if (certstart) + { + // X509_cmp_current_time() will return 1 when certstart is in the future + // and zero if there is an error. In both cases we treat the certificate as invalid. + if (X509_cmp_current_time(certstart) < 0) result = OFFalse; + } + } + return result; +} + + long SiCertificate::getCertKeyBits() { long certPubKeyBits = 0; /* certificate number of bits in public key */ @@ -301,6 +432,226 @@ long SiCertificate::getCertKeyBits() return certPubKeyBits; } +const char *SiCertificate::getCertCurveName() +{ + const char *result = NULL; +#ifndef OPENSSL_NO_EC + if (x509) + { + EVP_PKEY *pkey = X509_extract_key(x509); + if (pkey && EVP_PKEY_type(EVP_PKEY_id(pkey)) == EVP_PKEY_EC) + { + // we have an elliptic curve. Access EC key. +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); +#else + const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey); +#endif + if (eckey) + { + // access EC group within EC key + const EC_GROUP *ecgroup = EC_KEY_get0_group(eckey); + if (ecgroup) + { + // check if we have a named curve + int nid = EC_GROUP_get_curve_name(ecgroup); + if (nid > 0) + { + result = OBJ_nid2sn(nid); + } + else result = "unnamed curve"; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + EC_KEY_free(eckey); +#endif + } + EVP_PKEY_free(pkey); + } + } +#endif + return result; +} + +OFBool SiCertificate::isWeakKey() +{ + OFBool result = OFTrue; + long bits = getCertKeyBits(); + switch (getKeyType()) + { + case EKT_RSA: + case EKT_DSA: + case EKT_DH: + if (bits >= 1024) result = OFFalse; + break; + case EKT_EC: + if (bits >= 256) result = OFFalse; + break; + case EKT_none: // should never happen + break; + } + return result; +} + +void SiCertificate::checkForWeakKey() +{ + if (isWeakKey()) + { + switch (getKeyType()) + { + case EKT_RSA: + DCMSIGN_WARN("Certificate contains a weak key: RSA, " << getCertKeyBits() << " bits"); + break; + case EKT_DSA: + DCMSIGN_WARN("Certificate contains a weak key: DSA, " << getCertKeyBits() << " bits"); + break; + case EKT_EC: + DCMSIGN_WARN("Certificate contains a weak key: EC, " << getCertKeyBits() << " bits"); + break; + case EKT_DH: + DCMSIGN_WARN("Certificate contains a weak key: DH, " << getCertKeyBits() << " bits"); + break; + case EKT_none: // should never happen + DCMSIGN_WARN("Certificate contains a weak key: unknown type"); + break; + } + } +} + +OFCondition SiCertificate::convertGeneralizedTime(const ASN1_GENERALIZEDTIME *d, OFDateTime& dt) +{ + // This method is derived from OpenSSL's asn1_generalizedtime_to_tm(), + // which was introduced in OpenSSL 1.0.2. Since we still support OpenSSL 1.0.1, + // we cannot use that function. + + static const int minval[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + static const int maxval[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; + + unsigned int dt_year = 0; + unsigned int dt_month = 0; + unsigned int dt_day = 0; + unsigned int dt_hour = 0; + unsigned int dt_minute = 0; + double dt_second = 0.0; + double dt_timeZone = 0.0; + char *a; + int n, i, l, o; + + if (d == NULL) return EC_IllegalCall; + if (d->type != V_ASN1_GENERALIZEDTIME) return EC_IllegalCall; + l = d->length; + a = (char *)d->data; + o = 0; + /* + * GENERALIZEDTIME is similar to UTCTIME except the year is represented + * as YYYY. This stuff treats everything as a two digit field so make + * first two fields 00 to 99 + */ + if (l < 13) return EC_IllegalCall; + for (i = 0; i < 7; i++) { + if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { + i++; + dt_second = 0; + break; + } + if ((a[o] < '0') || (a[o] > '9')) return EC_IllegalCall; + n = a[o] - '0'; + if (++o > l) return EC_IllegalCall; + + if ((a[o] < '0') || (a[o] > '9')) return EC_IllegalCall; + n = (n * 10) + a[o] - '0'; + if (++o > l) return EC_IllegalCall; + + if ((n < minval[i]) || (n > maxval[i])) return EC_IllegalCall; + switch (i) + { + case 0: + dt_year = n * 100; + break; + case 1: + dt_year += n; + break; + case 2: + dt_month = n; + break; + case 3: + dt_day = n; + break; + case 4: + dt_hour = n; + break; + case 5: + dt_minute = n; + break; + case 6: + dt_second = n; + break; + } + } + /* + * Optional fractional seconds: decimal point followed by one or more + * digits. + */ + if (a[o] == '.') { + if (++o > l) return EC_IllegalCall; + i = o; + while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) o++; + /* Must have at least one digit after decimal point */ + if (i == o) return EC_IllegalCall; + } + + if (a[o] == 'Z') + o++; + else if ((a[o] == '+') || (a[o] == '-')) { + int offsign = a[o] == '-' ? 1 : -1, offset = 0; + o++; + if (o + 4 > l) + return EC_IllegalCall; + for (i = 7; i < 9; i++) { + if ((a[o] < '0') || (a[o] > '9')) return EC_IllegalCall; + n = a[o] - '0'; + o++; + if ((a[o] < '0') || (a[o] > '9')) return EC_IllegalCall; + n = (n * 10) + a[o] - '0'; + if ((n < minval[i]) || (n > maxval[i])) return EC_IllegalCall; + if (i == 7) + offset = n * 3600; + else if (i == 8) + offset += n * 60; + o++; + } + if (offset) dt_timeZone = offset / 3600.0 * offsign; + } else if (a[o]) { + /* Missing time zone information. */ + return EC_IllegalCall; + } + if (! dt.setDateTime(dt_year, dt_month, dt_day, dt_hour, dt_minute, dt_second, dt_timeZone)) return EC_IllegalCall; + + return ((o == l) ? EC_Normal : EC_IllegalCall); +} + + +OFCondition SiCertificate::convertASN1Time(const ASN1_TIME *d, OFDateTime& dt) +{ + if (d) + { +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + // Before OpenSSL 1.1.0, the first parameter of ASN1_TIME_to_generalizedtime() + // was not declared const, as it should be + ASN1_GENERALIZEDTIME *gm = ASN1_TIME_to_generalizedtime(OFconst_cast(ASN1_TIME *, d), NULL); +#else + ASN1_GENERALIZEDTIME *gm = ASN1_TIME_to_generalizedtime(d, NULL); +#endif + if (gm) + { + OFCondition result = convertGeneralizedTime(gm, dt); + ASN1_GENERALIZEDTIME_free(gm); + return result; + } + } + return EC_IllegalCall; +} + + #else /* WITH_OPENSSL */ int sicert_cc_dummy_to_keep_linker_from_moaning = 0; diff --git a/dcmsign/libsrc/sicertvf.cc b/dcmsign/libsrc/sicertvf.cc index 5de5efb9..92a775e0 100644 --- a/dcmsign/libsrc/sicertvf.cc +++ b/dcmsign/libsrc/sicertvf.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2017, OFFIS e.V. + * Copyright (C) 1998-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -35,14 +35,31 @@ END_EXTERN_C SiCertificateVerifier::SiCertificateVerifier() : x509store(NULL) +, x509untrusted(NULL) +, enableCRLverification(OFFalse) , errorCode(0) { x509store = X509_STORE_new(); + x509untrusted = sk_X509_new_null(); } + SiCertificateVerifier::~SiCertificateVerifier() { - if (x509store) X509_STORE_free(x509store); + X509_STORE_free(x509store); + sk_X509_pop_free(x509untrusted, X509_free); +} + + +X509_STORE *SiCertificateVerifier::getTrustedCertStore() +{ + return x509store; +} + + +stack_st_X509 *SiCertificateVerifier::getUntrustedCerts() +{ + return x509untrusted; } @@ -56,6 +73,56 @@ OFCondition SiCertificateVerifier::addTrustedCertificateFile(const char *fileNam } +OFCondition SiCertificateVerifier::addUntrustedCertificateFile(const char *fileName, int fileType) +{ + OFCondition result = EC_Normal; + if (x509untrusted) + { + // PEM has different loading code because a PEM file can contain several certificates and CRLs + if (fileType == X509_FILETYPE_PEM) + { + BIO *bio = BIO_new_file(fileName, "r"); + if (bio) + { + STACK_OF(X509_INFO) *x509infostack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + if (x509infostack) + { + for (int i = 0; i < sk_X509_INFO_num(x509infostack); i++) + { + X509_INFO *xi = sk_X509_INFO_value(x509infostack, i); + if (xi->x509) + { + // move certificate to our list of untrusted certificates + sk_X509_push(x509untrusted, xi->x509); + xi->x509 = NULL; + } + } + // delete the remaining x509infostack + sk_X509_INFO_pop_free(x509infostack, X509_INFO_free); + } else result = SI_EC_CannotRead; + BIO_free(bio); + } else result = SI_EC_CannotRead; + } + else if (fileType == X509_FILETYPE_ASN1) + { + // load a single certificate in ASN.1 DER format + BIO *bio = BIO_new_file(fileName, "rb"); + if (bio) + { + X509 *xcert = d2i_X509_bio(bio, NULL); + if (xcert) + { + sk_X509_push(x509untrusted, xcert); + } else result = SI_EC_CannotRead; + BIO_free(bio); + } else result = SI_EC_CannotRead; + } else result = SI_EC_InvalidFiletype; + } else result = SI_EC_CannotRead; + + return result; +} + + OFCondition SiCertificateVerifier::addTrustedCertificateDir(const char *pathName, int fileType) { /* fileType should be X509_FILETYPE_PEM or X509_FILETYPE_ASN1 */ @@ -80,18 +147,15 @@ OFCondition SiCertificateVerifier::addCertificateRevocationList(const char *file if (fileType == X509_FILETYPE_ASN1) { x509crl = d2i_X509_CRL_bio(in, NULL); - if (x509crl) - { - X509_STORE_add_crl(x509store, x509crl); - result = EC_Normal; - } } else { x509crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - if (x509crl) - { - X509_STORE_add_crl(x509store, x509crl); - result = EC_Normal; - } + } + if (x509crl) + { + X509_STORE_add_crl(x509store, x509crl); // creates a copy of the CRL object + X509_CRL_free(x509crl); + enableCRLverification = OFTrue; + result = EC_Normal; } } BIO_free(in); @@ -101,6 +165,31 @@ OFCondition SiCertificateVerifier::addCertificateRevocationList(const char *file } +void SiCertificateVerifier::setCRLverification(OFBool enabled) +{ + enableCRLverification = enabled; +} + + +extern "C" +{ + int sicertvf_verify_callback(int deflt, X509_STORE_CTX *ctx); +} + +int sicertvf_verify_callback(int deflt, X509_STORE_CTX *ctx) +{ + if (ctx) + { + void *p = X509_STORE_CTX_get_ex_data(ctx, 0); + if (p) + { + SiCertificateVerifier *pthis = OFreinterpret_cast(SiCertificateVerifier *, p); + return pthis->verifyCallback(deflt, ctx); + } + } + return deflt; +} + OFCondition SiCertificateVerifier::verifyCertificate(SiCertificate& certificate) { errorCode = 0; @@ -108,7 +197,22 @@ OFCondition SiCertificateVerifier::verifyCertificate(SiCertificate& certificate) if (rawcert == NULL) return SI_EC_VerificationFailed_NoCertificate; X509_STORE_CTX *ctx = X509_STORE_CTX_new(); - X509_STORE_CTX_init(ctx, x509store, rawcert, NULL); + X509_STORE_CTX_init(ctx, x509store, rawcert, x509untrusted); + + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); + if (param) + { + if (enableCRLverification) + { + // enable CRL checking for the signer certificate + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + } + X509_VERIFY_PARAM_set_depth(param, 100); // that's the OpenSSL default + X509_STORE_CTX_set0_param(ctx, param); + } + + X509_STORE_CTX_set_ex_data(ctx, 0, OFreinterpret_cast(void *, this)); + X509_STORE_CTX_set_verify_cb(ctx, sicertvf_verify_callback); // If a complete chain can be built and validated X509_verify_cert() returns 1, // otherwise it returns zero, in exceptional circumstances it can also return a negative code. @@ -121,6 +225,25 @@ OFCondition SiCertificateVerifier::verifyCertificate(SiCertificate& certificate) if (ok == 1) return EC_Normal; else return SI_EC_VerificationFailed_NoTrust; } +int SiCertificateVerifier::verifyCallback(int deflt, X509_STORE_CTX *ctx) +{ + if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_REVOKED) + { + // The signer certificate is on the revocation list. By default, this means that + // the certificate verification will fail, independent from the timestamp of the signature + // and the timestamp of the revocation. At this point we could add additional code that + // compares the time of revocation with the DICOM signature datetime or (preferrably) a + // certified timestamp that might also be present. If the revocation occured after the time of + // signature, we could still accept the certificate and thus the signature. + // For now, we retain the OpenSSL default behaviour. + } + return deflt; +} + +OFBool SiCertificateVerifier::lastErrorIsCertExpiry() const +{ + return (errorCode == X509_V_ERR_CERT_HAS_EXPIRED); +} const char *SiCertificateVerifier::lastError() const { diff --git a/dcmsign/libsrc/sicreapr.cc b/dcmsign/libsrc/sicreapr.cc index 843f1042..9584d960 100644 --- a/dcmsign/libsrc/sicreapr.cc +++ b/dcmsign/libsrc/sicreapr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2010, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -26,68 +26,685 @@ #include "dcmtk/dcmsign/sicreapr.h" #include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmsign/sitypes.h" +SiCreatorProfile::SiCreatorProfile() +: containsRawData_(OFFalse) +{ +} -OFBool SiCreatorProfile::attributeRequired(const DcmTagKey& key) const +OFBool SiCreatorProfile::attributeRequiredIfPresent(const DcmTagKey& key) const { - /* SOP Class and Instance UIDs */ + // This list of attribute tags was extracted from DICOM 2019c. + // Attribute tags occuring in multiple modules were commented out + // but remain in the source code to simplify a comparison with the + // module tables in a later edition of the DICOM standard. + + // The following attributes must be included in the signature if present + // according to the Creator RSA Digital Signature Profile + // (DICOM Part 15, section C.2): + + // the SOP Class and Instance UIDs if (key == DCM_SOPClassUID) return OFTrue; if (key == DCM_SOPInstanceUID) return OFTrue; - /* SOP Creation Date and Time, if present */ + // the SOP Creation Date and Time, if present if (key == DCM_InstanceCreationDate) return OFTrue; if (key == DCM_InstanceCreationTime) return OFTrue; - /* Study and Series Instance UIDs */ + // the Study and Series Instance UIDs if (key == DCM_StudyInstanceUID) return OFTrue; if (key == DCM_SeriesInstanceUID) return OFTrue; - /* Any attributes of the General Equipment module that are present */ - + // any attributes of the General Equipment Module that are present if (key == DCM_Manufacturer) return OFTrue; if (key == DCM_InstitutionName) return OFTrue; if (key == DCM_InstitutionAddress) return OFTrue; if (key == DCM_StationName) return OFTrue; if (key == DCM_InstitutionalDepartmentName) return OFTrue; + if (key == DCM_InstitutionalDepartmentTypeCodeSequence) return OFTrue; if (key == DCM_ManufacturerModelName) return OFTrue; if (key == DCM_DeviceSerialNumber) return OFTrue; if (key == DCM_SoftwareVersions) return OFTrue; + if (key == DCM_GantryID) return OFTrue; + if (key == DCM_UDISequence) return OFTrue; + if (key == DCM_DeviceUID) return OFTrue; if (key == DCM_SpatialResolution) return OFTrue; if (key == DCM_DateOfLastCalibration) return OFTrue; if (key == DCM_TimeOfLastCalibration) return OFTrue; if (key == DCM_PixelPaddingValue) return OFTrue; - /* Any overlay data present */ - if ((key.getGroup() >= 0x6000) && (key.getGroup() < 0x6020) && ((key.getGroup() & 0x0001) == 0)) return OFTrue; + // any attributes of the Overlay Plane Module that are present + if (key == DCM_OverlayRows) return OFTrue; + if (key == DCM_OverlayColumns) return OFTrue; + if (key == DCM_OverlayType) return OFTrue; + if (key == DCM_OverlayOrigin) return OFTrue; + if (key == DCM_OverlayBitsAllocated) return OFTrue; + if (key == DCM_OverlayBitPosition) return OFTrue; + if (key == DCM_OverlayData) return OFTrue; + if (key == DCM_OverlayDescription) return OFTrue; + if (key == DCM_OverlaySubtype) return OFTrue; + if (key == DCM_OverlayLabel) return OFTrue; + if (key == DCM_ROIArea) return OFTrue; + if (key == DCM_ROIMean) return OFTrue; + if (key == DCM_ROIStandardDeviation) return OFTrue; - /* Any image data present - we assume this means the Image Pixel Module and not just PixelData */ - if (key.getGroup() == 0x0028) + // any attributes of the Curve Module that are present + if ((key.getGroup() >= 0x5000) && (key.getGroup() < 0x5020) && ((key.getGroup() & 1) == 0)) { - Uint16 elem = key.getElement(); - if (elem == 0x0002) return OFTrue; // DCM_SamplesPerPixel - if (elem == 0x0004) return OFTrue; // DCM_PhotometricInterpretation - if (elem == 0x0006) return OFTrue; // DCM_PlanarConfiguration - if (elem == 0x0010) return OFTrue; // DCM_Rows - if (elem == 0x0011) return OFTrue; // DCM_Columns - if (elem == 0x0034) return OFTrue; // DCM_PixelAspectRatio - if (elem == 0x0100) return OFTrue; // DCM_BitsAllocated - if (elem == 0x0101) return OFTrue; // DCM_BitsStored - if (elem == 0x0102) return OFTrue; // DCM_HighBit - if (elem == 0x0103) return OFTrue; // DCM_PixelRepresentation - if (elem == 0x0106) return OFTrue; // DCM_SmallestImagePixelValue - if (elem == 0x0107) return OFTrue; // DCM_LargestImagePixelValue - if (elem == 0x1101) return OFTrue; // DCM_RedPaletteColorLookupTableDescriptor - if (elem == 0x1102) return OFTrue; // DCM_GreenPaletteColorLookupTableDescriptor - if (elem == 0x1103) return OFTrue; // DCM_BluePaletteColorLookupTableDescriptor - if (elem == 0x1201) return OFTrue; // DCM_RedPaletteColorLookupTableData - if (elem == 0x1202) return OFTrue; // DCM_GreenPaletteColorLookupTableData - if (elem == 0x1203) return OFTrue; // DCM_BluePaletteColorLookupTableData + switch (key.getElement()) + { + case 0x0005: // CurveDimensions (retired) + case 0x0010: // NumberOfPoints (retired) + case 0x0103: // DataValueRepresentation (retired) + case 0x3000: // CurveData (retired) + case 0x0022: // CurveDescription (retired) + case 0x0030: // AxisUnits (retired) + case 0x0040: // AxisLabels (retired) + case 0x0104: // MinimumCoordinateValue (retired) + case 0x0105: // MaximumCoordinateValue (retired) + case 0x0106: // CurveRange (retired) + case 0x0110: // CurveDataDescriptor (retired) + case 0x0112: // CoordinateStartValue (retired) + case 0x0114: // CoordinateStepValue (retired) + case 0x2500: // CurveLabel (retired) + case 0x2600: // ReferencedOverlaySequence (retired) + return OFTrue; + break; + default: + /* nothing */ + break; + } } + + // any attributes of the Graphic Annotation Module that are present + if (key == DCM_GraphicAnnotationSequence) return OFTrue; + + // any attributes of the General Image Module that are present + if (key == DCM_InstanceNumber) return OFTrue; + if (key == DCM_PatientOrientation) return OFTrue; + if (key == DCM_ContentDate) return OFTrue; + if (key == DCM_ContentTime) return OFTrue; + if (key == DCM_ImageType) return OFTrue; + if (key == DCM_AcquisitionNumber) return OFTrue; + if (key == DCM_AcquisitionDate) return OFTrue; + if (key == DCM_AcquisitionTime) return OFTrue; + if (key == DCM_AcquisitionDateTime) return OFTrue; + if (key == DCM_ImagesInAcquisition) return OFTrue; + if (key == DCM_ImageComments) return OFTrue; + if (key == DCM_QualityControlImage) return OFTrue; + if (key == DCM_BurnedInAnnotation) return OFTrue; + if (key == DCM_RecognizableVisualFeatures) return OFTrue; + if (key == DCM_LossyImageCompression) return OFTrue; + if (key == DCM_LossyImageCompressionRatio) return OFTrue; + if (key == DCM_LossyImageCompressionMethod) return OFTrue; + if (key == DCM_IconImageSequence) return OFTrue; + if (key == DCM_PresentationLUTShape) return OFTrue; + if (key == DCM_IrradiationEventUID) return OFTrue; + if (key == DCM_RealWorldValueMappingSequence) return OFTrue; + if (key == DCM_ImageLaterality) return OFTrue; + if (key == DCM_AnatomicRegionSequence) return OFTrue; + if (key == DCM_PrimaryAnatomicStructureSequence) return OFTrue; + + // any attributes of the Image Pixel Module that are present + if (key == DCM_SamplesPerPixel) return OFTrue; + if (key == DCM_PhotometricInterpretation) return OFTrue; + if (key == DCM_Rows) return OFTrue; + if (key == DCM_Columns) return OFTrue; + if (key == DCM_BitsAllocated) return OFTrue; + if (key == DCM_BitsStored) return OFTrue; + if (key == DCM_HighBit) return OFTrue; + if (key == DCM_PixelRepresentation) return OFTrue; + if (key == DCM_PlanarConfiguration) return OFTrue; + if (key == DCM_PixelAspectRatio) return OFTrue; + if (key == DCM_SmallestImagePixelValue) return OFTrue; + if (key == DCM_LargestImagePixelValue) return OFTrue; + if (key == DCM_RedPaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_GreenPaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_BluePaletteColorLookupTableDescriptor) return OFTrue; + if (key == DCM_RedPaletteColorLookupTableData) return OFTrue; + if (key == DCM_GreenPaletteColorLookupTableData) return OFTrue; + if (key == DCM_BluePaletteColorLookupTableData) return OFTrue; + if (key == DCM_ICCProfile) return OFTrue; + if (key == DCM_ColorSpace) return OFTrue; if (key == DCM_PixelData) return OFTrue; + if (key == DCM_PixelDataProviderURL) return OFTrue; + if (key == DCM_PixelPaddingRangeLimit) return OFTrue; + if (key == DCM_ExtendedOffsetTable) return OFTrue; + if (key == DCM_ExtendedOffsetTableLengths) return OFTrue; + + // any attributes of the SR Document General Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + if (key == DCM_PreliminaryFlag) return OFTrue; + if (key == DCM_CompletionFlag) return OFTrue; + if (key == DCM_CompletionFlagDescription) return OFTrue; + if (key == DCM_VerificationFlag) return OFTrue; + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + if (key == DCM_VerifyingObserverSequence) return OFTrue; + if (key == DCM_AuthorObserverSequence) return OFTrue; + if (key == DCM_ParticipantSequence) return OFTrue; + if (key == DCM_CustodialOrganizationSequence) return OFTrue; + if (key == DCM_PredecessorDocumentsSequence) return OFTrue; + if (key == DCM_IdenticalDocumentsSequence) return OFTrue; + if (key == DCM_ReferencedRequestSequence) return OFTrue; + if (key == DCM_PerformedProcedureCodeSequence) return OFTrue; + if (key == DCM_CurrentRequestedProcedureEvidenceSequence) return OFTrue; + if (key == DCM_PertinentOtherEvidenceSequence) return OFTrue; + if (key == DCM_ReferencedInstanceSequence) return OFTrue; + + // any attributes of the SR Document Content Module that are present + if (key == DCM_ValueType) return OFTrue; + if (key == DCM_ConceptNameCodeSequence) return OFTrue; + if (key == DCM_ContinuityOfContent) return OFTrue; + if (key == DCM_ContentTemplateSequence) return OFTrue; + if (key == DCM_ObservationDateTime) return OFTrue; + if (key == DCM_ObservationUID) return OFTrue; + if (key == DCM_ContentSequence) return OFTrue; + + // any attributes of the Waveform Module that are present + if (key == DCM_WaveformSequence) return OFTrue; + if (key == DCM_WaveformDataDisplayScale) return OFTrue; + if (key == DCM_WaveformDisplayBackgroundCIELabValue) return OFTrue; + if (key == DCM_WaveformPresentationGroupSequence) return OFTrue; + + // any attributes of the Waveform Annotation Module that are present + if (key == DCM_WaveformAnnotationSequence) return OFTrue; + + // any attributes of the Multi-frame Functional Groups Module that are present + if (key == DCM_SharedFunctionalGroupsSequence) return OFTrue; + if (key == DCM_PerFrameFunctionalGroupsSequence) return OFTrue; + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + if (key == DCM_NumberOfFrames) return OFTrue; + if (key == DCM_StereoPairsPresent) return OFTrue; + if (key == DCM_ConcatenationFrameOffsetNumber) return OFTrue; + if (key == DCM_RepresentativeFrameNumber) return OFTrue; + if (key == DCM_ConcatenationUID) return OFTrue; + if (key == DCM_SOPInstanceUIDOfConcatenationSource) return OFTrue; + if (key == DCM_InConcatenationNumber) return OFTrue; + if (key == DCM_InConcatenationTotalNumber) return OFTrue; + + // any attributes of the Enhanced MR Image Module that are present + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + if (key == DCM_AcquisitionDuration) return OFTrue; + if (key == DCM_ReferencedRawDataSequence) return OFTrue; + if (key == DCM_ReferencedWaveformSequence) return OFTrue; + if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; + if (key == DCM_SourceImageEvidenceSequence) return OFTrue; + if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; + if (key == DCM_ContentQualification) return OFTrue; + if (key == DCM_ResonantNucleus) return OFTrue; + if (key == DCM_KSpaceFiltering) return OFTrue; + if (key == DCM_MagneticFieldStrength) return OFTrue; + if (key == DCM_ApplicableSafetyStandardAgency) return OFTrue; + if (key == DCM_ApplicableSafetyStandardDescription) return OFTrue; + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + if (key == DCM_IsocenterPosition) return OFTrue; + if (key == DCM_B1rms) return OFTrue; + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_PixelPresentation) return OFTrue; + if (key == DCM_VolumetricProperties) return OFTrue; + if (key == DCM_VolumeBasedCalculationTechnique) return OFTrue; + if (key == DCM_ComplexImageComponent) return OFTrue; + if (key == DCM_AcquisitionContrast) return OFTrue; + if (key == DCM_FunctionalSettlingPhaseFramesPresent) return OFTrue; + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PlanarConfiguration) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_ViewCodeSequence) return OFTrue; + if (key == DCM_SliceProgressionDirection) return OFTrue; + + // any attributes of the MR Spectroscopy Module that are present + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ResonantNucleus) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_k-SpaceFiltering) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_MagneticFieldStrength) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ApplicableSafetyStandardAgency) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ApplicableSafetyStandardDescription) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_IsocenterPosition) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_B1rms) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageType) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_VolumetricProperties) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_VolumeBasedCalculationTechnique) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ComplexImageComponent) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionContrast) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_TransmitterFrequency) return OFTrue; + if (key == DCM_SpectralWidth) return OFTrue; + if (key == DCM_ChemicalShiftReference) return OFTrue; + if (key == DCM_VolumeLocalizationTechnique) return OFTrue; + if (key == DCM_VolumeLocalizationSequence) return OFTrue; + if (key == DCM_Decoupling) return OFTrue; + if (key == DCM_DecoupledNucleus) return OFTrue; + if (key == DCM_DecouplingFrequency) return OFTrue; + if (key == DCM_DecouplingMethod) return OFTrue; + if (key == DCM_DecouplingChemicalShiftReference) return OFTrue; + if (key == DCM_TimeDomainFiltering) return OFTrue; + if (key == DCM_NumberOfZeroFills) return OFTrue; + if (key == DCM_BaselineCorrection) return OFTrue; + if (key == DCM_FrequencyCorrection) return OFTrue; + if (key == DCM_FirstOrderPhaseCorrection) return OFTrue; + if (key == DCM_WaterReferencedPhaseCorrection) return OFTrue; + if (key == DCM_WaterReferenceAcquisition) return OFTrue; + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + + // any attributes of the Raw Data Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + if (key == DCM_ContentLabel) return OFTrue; + if (key == DCM_ContentDescription) return OFTrue; + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ImageLaterality) return OFTrue; // also in General Image Module + if (key == DCM_CreatorVersionUID) return OFTrue; + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + + // if the Raw Data Module is present, we need to include all private tags into + // signature because the raw data as such is stored in private attributes. + if (((key.getGroup() & 1) == 1) && containsRawData_) return OFTrue; + + // any attributes of the Enhanced CT Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_MultienergyCTAcquisition) return OFTrue; + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedPresentationStateSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_IsocenterPosition) return OFTrue; // also in Enhanced MR Image Module + + // any attributes of the Enhanced XA/XRF Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_PlanesInAcquisition) return OFTrue; + if (key == DCM_PlaneIdentification) return OFTrue; + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + if (key == DCM_AcquisitionProtocolName) return OFTrue; + if (key == DCM_AcquisitionProtocolDescription) return OFTrue; + if (key == DCM_ScanOptions) return OFTrue; + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_PatientOrientationCodeSequence) return OFTrue; // also in General Image Module + if (key == DCM_PatientGantryRelationshipCodeSequence) return OFTrue; + if (key == DCM_ExaminedBodyThickness) return OFTrue; + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_ReferencedOtherPlaneSequence) return OFTrue; + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + + // any attributes of the Segmentation Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + if (key == DCM_ImageOrientationSlide) return OFTrue; + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_SegmentationType) return OFTrue; + if (key == DCM_SegmentationFractionalType) return OFTrue; + if (key == DCM_MaximumFractionalValue) return OFTrue; + if (key == DCM_SegmentsOverlap) return OFTrue; + if (key == DCM_SegmentSequence) return OFTrue; + + // any attributes of the Encapsulated Document Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_ImageLaterality) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + if (key == DCM_SourceInstanceSequence) return OFTrue; + if (key == DCM_DocumentTitle) return OFTrue; + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + if (key == DCM_DocumentClassCodeSequence) return OFTrue; + // if (key == DCM_VerificationFlag) return OFTrue; // also in SR Document General Module + if (key == DCM_HL7InstanceIdentifier) return OFTrue; + // if (key == DCM_PredecessorDocumentsSequence) return OFTrue; // also in SR Document General Module + // if (key == DCM_IdenticalDocumentsSequence) return OFTrue; // also in SR Document General Module + if (key == DCM_MIMETypeOfEncapsulatedDocument) return OFTrue; + if (key == DCM_ListOfMIMETypes) return OFTrue; + if (key == DCM_EncapsulatedDocument) return OFTrue; + if (key == DCM_EncapsulatedDocumentLength) return OFTrue; + // if (key == DCM_ValueType) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContentSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContinuityOfContent) return OFTrue; // also in SR Document Content Module + // if (key == DCM_ContentTemplateSequence) return OFTrue; // also in SR Document Content Module + + // any attributes of the X-Ray 3D Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + if (key == DCM_SourceIrradiationEventSequence) return OFTrue; + + // any attributes of the Enhanced PET Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionNumber) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedWaveformSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SourceImageEvidenceSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + + // any attributes of the Enhanced US Image Module that are present + // if (key == DCM_ImageType) return OFTrue; // also in General Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + if (key == DCM_DimensionOrganizationType) return OFTrue; + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_PositionMeasuringDeviceUsed) return OFTrue; + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + if (key == DCM_RescaleIntercept) return OFTrue; + if (key == DCM_RescaleSlope) return OFTrue; + if (key == DCM_SourceImageSequence) return OFTrue; + if (key == DCM_ReferencedImageSequence) return OFTrue; + // if (key == DCM_ReferencedRawDataSequence) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + if (key == DCM_NumberOfStages) return OFTrue; + if (key == DCM_StageNumber) return OFTrue; + if (key == DCM_StageCodeSequence) return OFTrue; + if (key == DCM_EventTimerSequence) return OFTrue; + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_RecognizableVisualFeatures) return OFTrue; // also in General Image Module + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_TransducerData) return OFTrue; + if (key == DCM_TransducerGeometryCodeSequence) return OFTrue; + if (key == DCM_TransducerBeamSteeringCodeSequence) return OFTrue; + if (key == DCM_TransducerApplicationCodeSequence) return OFTrue; + if (key == DCM_ProcessingFunction) return OFTrue; + if (key == DCM_MechanicalIndex) return OFTrue; + if (key == DCM_BoneThermalIndex) return OFTrue; + if (key == DCM_CranialThermalIndex) return OFTrue; + if (key == DCM_SoftTissueThermalIndex) return OFTrue; + if (key == DCM_DepthsOfFocus) return OFTrue; + if (key == DCM_DepthOfScanField) return OFTrue; + + // any attributes of the Surface Segmentation Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentLabel) return OFTrue; // also in Raw Data Module + // if (key == DCM_ContentDescription) return OFTrue; // also in Raw Data Module + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + if (key == DCM_AlternateContentDescriptionSequence) return OFTrue; + if (key == DCM_ContentCreatorName) return OFTrue; + if (key == DCM_ContentCreatorIdentificationCodeSequence) return OFTrue; + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + // if (key == DCM_SegmentSequence) return OFTrue; // also in Segmentation Image Module + + // any attributes of the Surface Mesh Module that are present + if (key == DCM_NumberOfSurfaces) return OFTrue; + if (key == DCM_SurfaceSequence) return OFTrue; + + // any attributes of the Structured Display Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentLabel) return OFTrue; // also in Raw Data Module + // if (key == DCM_ContentDescription) return OFTrue; // also in Raw Data Module + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_AlternateContentDescriptionSequence) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorName) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorIdentificationCodeSequence) return OFTrue; // also in Surface Segmentation Module + if (key == DCM_PresentationCreationDate) return OFTrue; + if (key == DCM_PresentationCreationTime) return OFTrue; + if (key == DCM_NumberOfScreens) return OFTrue; + if (key == DCM_NominalScreenDefinitionSequence) return OFTrue; + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + if (key == DCM_StructuredDisplayBackgroundCIELabValue) return OFTrue; + if (key == DCM_EmptyImageBoxCIELabValue) return OFTrue; + if (key == DCM_HangingProtocolName) return OFTrue; + if (key == DCM_HangingProtocolCreator) return OFTrue; + + // any attributes of the Structured Display Annotation Module that are present + if (key == DCM_StructuredDisplayTextBoxSequence) return OFTrue; + + // any attributes of the Structured Display Image Box Module that are present + if (key == DCM_StructuredDisplayImageBoxSequence) return OFTrue; + if (key == DCM_ImageBoxSynchronizationSequence) return OFTrue; + + // any Attributes of the Implant Template Module that are present + // if (key == DCM_Manufacturer) return OFTrue; // also in General Equipment Module + if (key == DCM_FrameOfReferenceUID) return OFTrue; + if (key == DCM_ImplantName) return OFTrue; + if (key == DCM_ImplantSize) return OFTrue; + if (key == DCM_ImplantPartNumber) return OFTrue; + if (key == DCM_ImplantTemplateVersion) return OFTrue; + if (key == DCM_ReplacedImplantTemplateSequence) return OFTrue; + if (key == DCM_ImplantType) return OFTrue; + if (key == DCM_OriginalImplantTemplateSequence) return OFTrue; + if (key == DCM_DerivationImplantTemplateSequence) return OFTrue; + if (key == DCM_EffectiveDateTime) return OFTrue; + if (key == DCM_ImplantTargetAnatomySequence) return OFTrue; + if (key == DCM_NotificationFromManufacturerSequence) return OFTrue; + if (key == DCM_InformationFromManufacturerSequence) return OFTrue; + if (key == DCM_ImplantRegulatoryDisapprovalCodeSequence) return OFTrue; + if (key == DCM_OverallTemplateSpatialTolerance) return OFTrue; + if (key == DCM_MaterialsCodeSequence) return OFTrue; + if (key == DCM_CoatingMaterialsCodeSequence) return OFTrue; + if (key == DCM_ImplantTypeCodeSequence) return OFTrue; + if (key == DCM_FixationMethodCodeSequence) return OFTrue; + + // any Attributes of the Implant Assembly Template Module that are present + // if (key == DCM_EffectiveDateTime) return OFTrue; // also in Implant Template Module + if (key == DCM_ImplantAssemblyTemplateName) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateIssuer) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateVersion) return OFTrue; + if (key == DCM_ReplacedImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateType) return OFTrue; + if (key == DCM_OriginalImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_DerivationImplantAssemblyTemplateSequence) return OFTrue; + if (key == DCM_ImplantAssemblyTemplateTargetAnatomySequence) return OFTrue; + if (key == DCM_ProcedureTypeCodeSequence) return OFTrue; + if (key == DCM_SurgicalTechnique) return OFTrue; + // if (key == DCM_MIMETypeOfEncapsulatedDocument) return OFTrue; // also in Encapsulated Document Module + // if (key == DCM_EncapsulatedDocument) return OFTrue; // also in Encapsulated Document Module + if (key == DCM_ComponentTypesSequence) return OFTrue; + if (key == DCM_ComponentAssemblySequence) return OFTrue; + + // any Attributes of the Implant Template Group Module that are present + // if (key == DCM_EffectiveDateTime) return OFTrue; // also in Implant Template Module + if (key == DCM_ImplantTemplateGroupName) return OFTrue; + if (key == DCM_ImplantTemplateGroupDescription) return OFTrue; + if (key == DCM_ImplantTemplateGroupIssuer) return OFTrue; + if (key == DCM_ImplantTemplateGroupVersion) return OFTrue; + if (key == DCM_ReplacedImplantTemplateGroupSequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupTargetAnatomySequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupMembersSequence) return OFTrue; + if (key == DCM_ImplantTemplateGroupVariationDimensionSequence) return OFTrue; + + // any attributes of the Point Cloud Module that are present + if (key == DCM_SurfacePointsSequence) return OFTrue; + if (key == DCM_SurfacePointPresentationValueData) return OFTrue; + if (key == DCM_SurfacePointColorCIELabValueData) return OFTrue; + + // any attributes of the Enhanced Mammography Image Module that are present + if (key == DCM_PositionerMotion) return OFTrue; + if (key == DCM_PositionerType) return OFTrue; + // if (key == DCM_ContentQualification) return OFTrue; // also in Enhanced MR Image Module + // if (key == DCM_AcquisitionDateTime) return OFTrue; // also in General Image Module + // if (key == DCM_AcquisitionDuration) return OFTrue; // also in Enhanced MR Image Module + if (key == DCM_KVP) return OFTrue; + if (key == DCM_XRayTubeCurrentInmA) return OFTrue; + if (key == DCM_ExposureTimeInms) return OFTrue; + if (key == DCM_ExposureInmAs) return OFTrue; + if (key == DCM_FocalSpots) return OFTrue; + if (key == DCM_AnodeTargetMaterial) return OFTrue; + if (key == DCM_BodyPartThickness) return OFTrue; + if (key == DCM_CompressionForce) return OFTrue; + if (key == DCM_CompressionPressure) return OFTrue; + if (key == DCM_CompressionContactArea) return OFTrue; + if (key == DCM_PaddleDescription) return OFTrue; + if (key == DCM_ExposureControlMode) return OFTrue; + if (key == DCM_ExposureControlModeDescription) return OFTrue; + if (key == DCM_PatientOrientation) return OFTrue; + // if (key == DCM_ImageComments) return OFTrue; // also in General Image Module + // if (key == DCM_SamplesPerPixel) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PhotometricInterpretation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsAllocated) return OFTrue; // also in Image Pixel Module + // if (key == DCM_BitsStored) return OFTrue; // also in Image Pixel Module + // if (key == DCM_HighBit) return OFTrue; // also in Image Pixel Module + // if (key == DCM_PixelRepresentation) return OFTrue; // also in Image Pixel Module + // if (key == DCM_QualityControlImage) return OFTrue; // also in General Image Module + // if (key == DCM_BurnedInAnnotation) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompression) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionRatio) return OFTrue; // also in General Image Module + // if (key == DCM_LossyImageCompressionMethod) return OFTrue; // also in General Image Module + if (key == DCM_OrganDose) return OFTrue; + if (key == DCM_EntranceDoseInmGy) return OFTrue; + if (key == DCM_EntranceDoseDerivation) return OFTrue; + if (key == DCM_TypeOfDetectorMotion) return OFTrue; + // if (key == DCM_IconImageSequence) return OFTrue; // also in General Image Module + // if (key == DCM_PresentationLUTShape) return OFTrue; // also in General Image Module + + // any attributes of the Tractography Results Module that are present + // if (key == DCM_InstanceNumber) return OFTrue; // also in General Image Module + // if (key == DCM_ContentLabel) return OFTrue; // also in Raw Data Module + // if (key == DCM_ContentDescription) return OFTrue; // also in Raw Data Module + // if (key == DCM_ConceptNameCodeSequence) return OFTrue; // also in SR Document Content Module + // if (key == DCM_AlternateContentDescriptionSequence) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorName) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentCreatorIdentificationCodeSequence) return OFTrue; // also in Surface Segmentation Module + // if (key == DCM_ContentDate) return OFTrue; // also in General Image Module + // if (key == DCM_ContentTime) return OFTrue; // also in General Image Module + if (key == DCM_TrackSetSequence) return OFTrue; + // if (key == DCM_ReferencedInstanceSequence) return OFTrue; // also in SR Document General Module + + // any attributes of the Volumetric Graphic Annotation Module that are present + if (key == DCM_VolumetricAnnotationSequence) return OFTrue; + if (key == DCM_VolumetricPresentationInputAnnotationSequence) return OFTrue; return OFFalse; } + +OFBool SiCreatorProfile::checkRequiredAttributeList(DcmAttributeTag& tagList) const +{ + OFBool result = + containsTag(tagList, DCM_SOPClassUID) && + containsTag(tagList, DCM_StudyInstanceUID) && + containsTag(tagList, DCM_SeriesInstanceUID) && + containsTag(tagList, DCM_SOPInstanceUID); + + return result; +} + + +OFCondition SiCreatorProfile::inspectSignatureDataset(DcmItem &item) +{ + DcmElement *delem = NULL; + if (item.findAndGetElement(DCM_CreatorVersionUID, delem).good()) + { + // The CreatorVersionUID attribute is present in the dataset or item. + // Since this attribute only occurs in the Raw Data Module, this means that + // the Raw Data Module is present. + containsRawData_ = OFTrue; + } + else + { + containsRawData_ = OFFalse; + } + return EC_Normal; +} + +OFBool SiCreatorProfile::mainDatasetRequired() const +{ + return OFTrue; +} + #else /* WITH_OPENSSL */ int sicreapr_cc_dummy_to_keep_linker_from_moaning = 0; diff --git a/dcmsign/libsrc/siecdsa.cc b/dcmsign/libsrc/siecdsa.cc new file mode 100644 index 00000000..f1b35023 --- /dev/null +++ b/dcmsign/libsrc/siecdsa.cc @@ -0,0 +1,188 @@ +/* + * + * Copyright (C) 1998-2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Norbert Loxen, Marco Eichelberg + * + * Purpose: + * classes: SiECDSA + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/siecdsa.h" +#include "dcmtk/dcmsign/sicert.h" +#include "dcmtk/dcmsign/siprivat.h" + +BEGIN_EXTERN_C +#include +#include +#ifndef OPENSSL_NO_EC +#include +#include +#endif +END_EXTERN_C + +SiECDSA::SiECDSA(EC_KEY *key) +: ecdsa(key) +{ +} + +#ifndef OPENSSL_NO_EC + +SiECDSA::~SiECDSA() +{ + if (ecdsa) EC_KEY_free(ecdsa); +} + + +OFCondition SiECDSA::sign( + const unsigned char *inputHash, + unsigned long inputHashSize, + E_MACType inputHashAlgorithm, + unsigned char *outputSignature, + unsigned long &outputSignatureSize) +{ + if (ecdsa==NULL) return SI_EC_InitializationFailed; + int openSSLmac = 0; + switch (inputHashAlgorithm) + { + case EMT_SHA1: + openSSLmac = NID_sha1; + break; + case EMT_RIPEMD160: + openSSLmac = NID_ripemd160; + break; + case EMT_MD5: + openSSLmac = NID_md5; + break; + case EMT_SHA256: + openSSLmac = NID_sha256; + break; + case EMT_SHA384: + openSSLmac = NID_sha384; + break; + case EMT_SHA512: + openSSLmac = NID_sha512; + break; + } + unsigned int sigLen = 0; + int error = ECDSA_sign(openSSLmac, inputHash, (unsigned int)inputHashSize, outputSignature, &sigLen, ecdsa); + outputSignatureSize = sigLen; + if (error < 0) return SI_EC_OpenSSLFailure; + return EC_Normal; +} + + +OFCondition SiECDSA::verify( + const unsigned char *inputHash, + unsigned long inputHashSize, + E_MACType inputHashAlgorithm, + const unsigned char *inputSignature, + unsigned long inputSignatureSize, + OFBool &verified) +{ + verified = OFFalse; + if (ecdsa==NULL) return SI_EC_InitializationFailed; + int openSSLmac = 0; + switch (inputHashAlgorithm) + { + case EMT_SHA1: + openSSLmac = NID_sha1; + break; + case EMT_RIPEMD160: + openSSLmac = NID_ripemd160; + break; + case EMT_MD5: + openSSLmac = NID_md5; + break; + case EMT_SHA256: + openSSLmac = NID_sha256; + break; + case EMT_SHA384: + openSSLmac = NID_sha384; + break; + case EMT_SHA512: + openSSLmac = NID_sha512; + break; + } + + // we have to cast away const on inputSignature yet because of OpenSSL limitations + int error = ECDSA_verify(openSSLmac, inputHash, (unsigned int)inputHashSize, (unsigned char *)inputSignature, (unsigned int)inputSignatureSize, ecdsa); + + if (error < 0) + { + const char *err = ERR_reason_error_string(ERR_peek_error()); + if (err) DCMSIGN_ERROR("OpenSSL error: " << err); + return SI_EC_OpenSSLFailure; + } + else if (error > 0) verified = OFTrue; + + return EC_Normal; +} + + +unsigned long SiECDSA::getSize() const +{ + if (ecdsa == NULL) return 0; + return ECDSA_size(ecdsa); +} + +#else /* OPENSSL_NO_EC */ + +SiECDSA::~SiECDSA() +{ +} + +OFCondition SiECDSA::sign( + const unsigned char * /* inputHash */, + unsigned long /* inputHashSize */, + E_MACType /* inputHashAlgorithm */, + unsigned char * /* outputSignature */, + unsigned long& /* outputSignatureSize */) +{ + return SI_EC_EllipticCurveNotSupported; +} + +OFCondition SiECDSA::verify( + const unsigned char * /* inputHash */, + unsigned long /* inputHashSize */, + E_MACType /* inputHashAlgorithm */, + const unsigned char * /* inputSignature */, + unsigned long /* inputSignatureSize */, + OFBool& /* verified */) +{ + return SI_EC_EllipticCurveNotSupported; +} + +unsigned long SiECDSA::getSize() const +{ + return 0; +} + +#endif /* OPENSSL_NO_EC */ + +E_KeyType SiECDSA::keyType() const +{ + return EKT_EC; +} + +#else /* WITH_OPENSSL */ + +int SiECDSA_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/simaccon.cc b/dcmsign/libsrc/simaccon.cc index cdd91a60..2f2474a2 100644 --- a/dcmsign/libsrc/simaccon.cc +++ b/dcmsign/libsrc/simaccon.cc @@ -189,15 +189,65 @@ OFCondition SiMACConstructor::encodeDataset( result = tagListOut.putTagVal(element->getTag(), tagListOut.getVM()); } } + else + { + // the element is unsignable, but either the user or the active + // signature profile have requested its inclusion in the signature. + if (tagListIn) + { + // print a warning + DcmTag tag(element->getTag()); // we need to create a temporary copy of the tag + DCMSIGN_INFO("List of attributes to be signed contains unsignable element " << tag << " " << tag.getTagName() ); + result = SI_EC_AttributeNotSignable; + } + } } } /* done, flush stream buffer */ - result = flushBuffer(mac); + if (result.good()) result = flushBuffer(mac); item.transferEnd(); return result; } + +OFCondition SiMACConstructor::encodeDatasetForVerification( + DcmItem& item, + SiMAC& mac, + E_TransferSyntax oxfer, + DcmAttributeTag *tagListIn) +{ + if (! item.canWriteXfer(oxfer, EXS_Unknown)) return SI_EC_WrongTransferSyntax; + + OFCondition result = EC_Normal; + item.transferInit(); + unsigned long numElements = item.card(); + DcmElement *element; + for (unsigned long i=0; i < numElements; i++) + { + element = item.getElement(i); + if (result.good() && (inTagList(element, tagListIn))) + { + if (element->isSignable()) + { + // element is signable, we should encode it + result = encodeElement(element, mac, oxfer); + } + else + { + // print a warning + DcmTag tag(element->getTag()); // we need to create a temporary copy of the tag + DCMSIGN_INFO(" Signature contains unsignable element " << tag << " " << tag.getTagName() ); + result = SI_EC_VerificationFailed_AttributeNotSignable; + } + } + } + + /* done, flush stream buffer */ + if (result.good()) result = flushBuffer(mac); + item.transferEnd(); + return result; +} #else /* WITH_OPENSSL */ int simaccon_cc_dummy_to_keep_linker_from_moaning = 0; diff --git a/dcmsign/libsrc/sinullpr.cc b/dcmsign/libsrc/sinullpr.cc index 43d09c8b..ac525ad9 100644 --- a/dcmsign/libsrc/sinullpr.cc +++ b/dcmsign/libsrc/sinullpr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2010, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -37,11 +37,16 @@ OFBool SiNullProfile::isAllowableAlgorithmType(E_KeyType keyType) const return OFTrue; } -OFBool SiNullProfile::attributeRequired(const DcmTagKey& /* key */) const +OFBool SiNullProfile::attributeRequiredIfPresent(const DcmTagKey& /* key */) const { return OFFalse; } +OFBool SiNullProfile::checkRequiredAttributeList(DcmAttributeTag& /* tagList */) const +{ + return OFTrue; +} + OFBool SiNullProfile::attributeForbidden(const DcmTagKey& /* key */) const { return OFFalse; @@ -53,6 +58,17 @@ OFBool SiNullProfile::isAllowableTransferSyntax(E_TransferSyntax xfer) const return OFTrue; } +OFCondition SiNullProfile::inspectSignatureDataset(DcmItem & /* item */) +{ + return EC_Normal; +} + +OFBool SiNullProfile::mainDatasetRequired() const +{ + return OFFalse; +} + + #else /* WITH_OPENSSL */ int sinullpr_cc_dummy_to_keep_linker_from_moaning = 0; diff --git a/dcmsign/libsrc/siprivat.cc b/dcmsign/libsrc/siprivat.cc index 6e012794..d6bff55f 100644 --- a/dcmsign/libsrc/siprivat.cc +++ b/dcmsign/libsrc/siprivat.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -27,6 +27,7 @@ #include "dcmtk/dcmsign/siprivat.h" #include "dcmtk/dcmsign/sirsa.h" #include "dcmtk/dcmsign/sidsa.h" +#include "dcmtk/dcmsign/siecdsa.h" #include "dcmtk/dcmsign/sicert.h" #define INCLUDE_CSTRING @@ -94,7 +95,7 @@ void SiPrivateKey::setPrivateKeyPasswdFromConsole() OFCondition SiPrivateKey::loadPrivateKey(const char *filename, int filetype) { - OFCondition result = SI_EC_CannotRead; + OFCondition result = SI_EC_CannotRead; if (pkey) EVP_PKEY_free(pkey); pkey = NULL; if (filename) @@ -128,7 +129,7 @@ E_KeyType SiPrivateKey::getKeyType() const E_KeyType result = EKT_none; if (pkey) { - switch(EVP_PKEY_id(pkey)) + switch(EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: result = EKT_RSA; @@ -139,6 +140,9 @@ E_KeyType SiPrivateKey::getKeyType() const case EVP_PKEY_DH: result = EKT_DH; break; + case EVP_PKEY_EC: + result = EKT_EC; + break; default: /* nothing */ break; @@ -152,7 +156,7 @@ SiAlgorithm *SiPrivateKey::createAlgorithmForPrivateKey() { if (pkey) { - switch(EVP_PKEY_id(pkey)) + switch(EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: return new SiRSA(EVP_PKEY_get1_RSA(pkey)); @@ -160,12 +164,19 @@ SiAlgorithm *SiPrivateKey::createAlgorithmForPrivateKey() case EVP_PKEY_DSA: return new SiDSA(EVP_PKEY_get1_DSA(pkey)); /* break; */ + case EVP_PKEY_EC: +#ifdef OPENSSL_NO_EC + return new SiECDSA(NULL); +#else + return new SiECDSA(EVP_PKEY_get1_EC_KEY(pkey)); +#endif + /* break; */ case EVP_PKEY_DH: default: /* nothing */ break; } - } + } return NULL; } diff --git a/dcmsign/libsrc/sipurpos.cc b/dcmsign/libsrc/sipurpos.cc new file mode 100644 index 00000000..2afcf702 --- /dev/null +++ b/dcmsign/libsrc/sipurpos.cc @@ -0,0 +1,159 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiSignaturePurpose + * + */ +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sipurpos.h" +#include "dcmtk/dcmsign/sitypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/ofstd/ofstream.h" + +// code value constants +static const char *purposeCodeValue[] = +{ + NULL, + "1", "2", "3", "4", "5", "6", + "7", "8", "9", "10", "11", "12", + "13", "14", "15", "16", "17", "18" +}; + +static const size_t purposeCodeValueEntries = sizeof(purposeCodeValue) / sizeof(const char *); + +// code meaning constants +static const char *purposeCodeMeaning[] = +{ + NULL, + "Author's Signature", + "Coauthor's Signature", + "Co-participant's Signature", + "Transcriptionist/Recorder Signature", + "Verification Signature", + "Validation Signature", + "Consent Signature", + "Signature Witness Signature", + "Event Witness Signature", + "Identity Witness Signature", + "Consent Witness Signature", + "Interpreter Signature", + "Review Signature", + "Source Signature", + "Addendum Signature", + "Modification Signature", + "Administrative (Error/Edit) Signature", + "Timestamp Signature" +}; + +static const size_t purposeCodeMeaningEntries = sizeof(purposeCodeMeaning) / sizeof(const char *); + +const char *SiSignaturePurpose::getCodeValue(E_SignaturePurposeType purpose) +{ + size_t idx = OFstatic_cast(size_t, purpose); // cast the enum to size_t + if ((idx > 0) && (idx < purposeCodeValueEntries)) return purposeCodeValue[idx]; + return NULL; +} + +const char *SiSignaturePurpose::getCodeMeaning(E_SignaturePurposeType purpose) +{ + size_t idx = OFstatic_cast(size_t, purpose); // cast the enum to size_t + if ((idx > 0) && (idx < purposeCodeMeaningEntries)) return purposeCodeMeaning[idx]; + return NULL; +} + +const char *SiSignaturePurpose::getCodingSchemeDesignator(E_SignaturePurposeType /* purpose */) +{ + return "ASTM-sigpurpose"; +} + +OFCondition SiSignaturePurpose::insertDigitalSignaturePurposeCodeSQ(DcmItem& seqItem, E_SignaturePurposeType sigPurpose) +{ + if (sigPurpose == ESP_none) return EC_Normal; // no signature purpose defined + + OFCondition result = EC_Normal; + const char *codeValue = getCodeValue(sigPurpose); + const char *codeMeaning = getCodeMeaning(sigPurpose); + const char *codingSchemeDesignator = getCodingSchemeDesignator(sigPurpose); + + if (codeValue && codeMeaning && codingSchemeDesignator) + { + DcmItem *ditem = NULL; + result = seqItem.findOrCreateSequenceItem(DCM_DigitalSignaturePurposeCodeSequence, ditem); + if (ditem) + { + if (result.good()) result = ditem->putAndInsertString(DCM_CodingSchemeDesignator, codingSchemeDesignator); + if (result.good()) result = ditem->putAndInsertString(DCM_CodeValue, codeValue); + if (result.good()) result = ditem->putAndInsertString(DCM_CodeMeaning, codeMeaning); + } + } + else result = EC_IllegalCall; // we were called with an undefined signature purpose + return result; +} + +SiSignaturePurpose::E_SignaturePurposeType SiSignaturePurpose::determineOverridePurpose(E_SignaturePurposeType currentPurpose, E_SignaturePurposeType overridePurpose) +{ + if (overridePurpose != ESP_none) + { + if ((currentPurpose != ESP_none) && (currentPurpose != overridePurpose)) + { + // we have a conflict between user selection and profile requirements + DCMSIGN_WARN("Signature profile requires purpose code " << OFstatic_cast(int, overridePurpose) << ", ignoring user selection " << OFstatic_cast(int, currentPurpose) << "."); + } + // the signature profile overrides the user's selection + currentPurpose = overridePurpose; + } + return currentPurpose; +} + +SiSignaturePurpose::E_SignaturePurposeType SiSignaturePurpose::lookup(size_t num) +{ + if (num < purposeCodeValueEntries) return OFstatic_cast(E_SignaturePurposeType, num); else return ESP_none; +} + +void SiSignaturePurpose::printSignatureCodes(STD_NAMESPACE ostream& out) +{ + out << "\nDigital Signature Purpose Codes:\n" + " 1: Author's Signature\n" + " 2: Coauthor's Signature\n" + " 3: Co-participant's Signature\n" + " 4: Transcriptionist/Recorder Signature\n" + " 5: Verification Signature\n" + " 6: Validation Signature\n" + " 7: Consent Signature\n" + " 8: Signature Witness Signature\n" + " 9: Event Witness Signature\n" + " 10: Identity Witness Signature\n" + " 11: Consent Witness Signature\n" + " 12: Interpreter Signature\n" + " 13: Review Signature\n" + " 14: Source Signature\n" + " 15: Addendum Signature\n" + " 16: Modification Signature\n" + " 17: Administrative (Error/Edit) Signature\n" + " 18: Timestamp Signature\n" + << OFendl; + return; +} + +#else /* WITH_OPENSSL */ +int sipurpos_cc_dummy_to_keep_linker_from_moaning = 0; +#endif diff --git a/dcmsign/libsrc/sisprof.cc b/dcmsign/libsrc/sisprof.cc index ca2d3d8d..03e14256 100644 --- a/dcmsign/libsrc/sisprof.cc +++ b/dcmsign/libsrc/sisprof.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2010, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -30,6 +30,8 @@ #include "dcmtk/dcmsign/simac.h" /* for SiMAC */ #include "dcmtk/dcmsign/sialgo.h" /* for SiAlgorithm */ +#include "dcmtk/dcmdata/dcdeftag.h" + OFBool SiSecurityProfile::isAllowableMAC(const SiMAC& mac) const { return isAllowableMACType(mac.macType()); @@ -44,32 +46,65 @@ OFBool SiSecurityProfile::isAllowableAlgorithm(const SiAlgorithm& algo) const OFCondition SiSecurityProfile::updateAttributeList(DcmItem &item, DcmAttributeTag& tagList) { - OFCondition result = EC_Normal; unsigned long card = item.card(); if (card == 0) { // nothing to sign tagList.clear(); - return result; + return SI_EC_DatasetEmpty; } + + OFCondition result = EC_Normal; unsigned long maxArray = 2*card; Uint16 *array = new Uint16[maxArray]; if (array == NULL) return EC_MemoryExhausted; - unsigned long i=0; + unsigned long i=0; for (i=0; igetTag(); - if (key.isSignableTag()) + const DcmTag& key = elem->getTag(); + + if (containsTag(tagList, key)) + { + // tag is already in the list of elements to be signed. Check if this is permitted + if (elem->isSignable() && !attributeForbidden(key)) + { + array[2*i] = key.getGroup(); + array[2*i+1] = key.getElement(); + } + else if (attributeForbidden(key)) + { + DcmTag tag(key); + DCMSIGN_INFO("List of attributes to be signed contains element forbidden by signature profile: " << tag << " " << tag.getTagName() ); + result = SI_EC_AttributeNotSignable; + } + else + { + DcmTag tag(key); + DCMSIGN_INFO("List of attributes to be signed contains unsignable element " << tag << " " << tag.getTagName() ); + result = SI_EC_AttributeNotSignable; + } + } + else { - if ((attributeRequired(key))||((containsTag(tagList, key))&&(! attributeForbidden(key)))) + // tag is not in the list of elements to be signed. Check if we should include it + if (attributeRequiredIfPresent(key)) { - array[2*i] = key.getGroup(); - array[2*i+1] = key.getElement(); + if (elem->isSignable()) + { + array[2*i] = key.getGroup(); + array[2*i+1] = key.getElement(); + } + else + { + DcmTag tag(key); + DCMSIGN_INFO("List of attributes to be signed according to signature profile contains unsignable element " << tag << " " << tag.getTagName() ); + result = SI_EC_AttributeNotSignable; + } } } } @@ -85,19 +120,108 @@ OFCondition SiSecurityProfile::updateAttributeList(DcmItem &item, DcmAttributeTa array [j++] = array[i++]; } else i += 2; } - + // now copy nonzero entries from array to tagList tagList.clear(); - if (j > 0) + if (j > 0 && result.good()) { result = tagList.putUint16Array(array, j>>1); } + delete[] array; + + if (result.good()) + { + if (!checkRequiredAttributeList(tagList)) + { + result = SI_EC_RequiredAttributeMissing; + } + } + + return result; +} + + +OFCondition SiSecurityProfile::createAttributeList(DcmItem &item, DcmAttributeTag& tagList) +{ + unsigned long card = item.card(); + if (card == 0) return SI_EC_DatasetEmpty; + + OFCondition result = EC_Normal; + unsigned long maxArray = 2*card; + Uint16 *array = new Uint16[maxArray]; + if (array == NULL) return EC_MemoryExhausted; + unsigned long i=0; + for (i=0; igetTag(); + + if (attributeRequiredIfPresent(key)) + { + // attribute is present and required + if (elem->isSignable()) + { + array[2*i] = key.getGroup(); + array[2*i+1] = key.getElement(); + } + else + { + DcmTag tag(key); + DCMSIGN_INFO("List of attributes to be signed according to signature profile contains unsignable element " << tag << " " << tag.getTagName() ); + result = SI_EC_AttributeNotSignable; + } + } + else + { + // attribute is not required. Include it if permitted, ignore it otherwise. + if (elem->isSignable() && !attributeForbidden(key)) + { + array[2*i] = key.getGroup(); + array[2*i+1] = key.getElement(); + } + } + } + + // pack array + unsigned long j=0; + i = 0; + while (i < maxArray) + { + if (array[i] > 0) + { + array [j++] = array[i++]; + array [j++] = array[i++]; + } else i += 2; + } + + // now copy nonzero entries from array to tagList + tagList.clear(); + if (j > 0 && result.good()) + { + result = tagList.putUint16Array(array, j>>1); + } + delete[] array; + + if (result.good()) + { + if (!checkRequiredAttributeList(tagList)) + { + result = SI_EC_RequiredAttributeMissing; + } + } + return result; } OFBool SiSecurityProfile::checkAttributeList(DcmItem &item, DcmAttributeTag& tagList) { + // first check if all attributes that must be signed if present + // are included in the signature, if present DcmElement *elem = NULL; unsigned long card = item.card(); for (unsigned long i=0; ifindAndGetSequenceItem(DCM_DigitalSignaturePurposeCodeSequence, ditem2).good() && ditem2) + { + if (ditem2->findAndGetOFString(DCM_CodeValue, s).good()) + { + if (s == "5") return OFTrue; // we have digital signature purpose code "5", which means that a verification signature is present + } + } + } + else return OFFalse; // no (further) item found. There is no verification signature + + // check next item + ++itemNo; + } +} + + +OFCondition SiStructuredReportingProfile::inspectSignatureDataset(DcmItem& item) +{ + DcmElement *delem; + OFString s; + + // check if this is an SR document by looking up the most important + // attributes we expect in any SR document + if (item.findAndGetElement(DCM_ValueType, delem).good() && + item.findAndGetElement(DCM_ConceptNameCodeSequence, delem).good() && + item.findAndGetElement(DCM_ContentSequence, delem).good()) + { + // fine, this is an SR document + if (item.findAndGetOFString(DCM_VerificationFlag, s).good() && (s == "VERIFIED")) + { + // check if we already have a verification signature in this dataset + if (! haveVerificationSignature(item)) + { + DCMSIGN_WARN("SR document status is 'VERIFIED', but the verification signature is missing"); + } + } + return EC_Normal; + } + else + { + // not an SR document + return SI_EC_DatasetDoesNotMatchProfile; + } +} + +OFBool SiStructuredReportingProfile::mainDatasetRequired() const +{ + return OFTrue; +} + +#else /* WITH_OPENSSL */ + +int sisrpr_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/sisrvpr.cc b/dcmsign/libsrc/sisrvpr.cc new file mode 100644 index 00000000..de6b61b8 --- /dev/null +++ b/dcmsign/libsrc/sisrvpr.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiStructuredReportingVerificationProfile + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sisrvpr.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmsign/sitypes.h" + +OFBool SiStructuredReportingVerificationProfile::attributeRequiredIfPresent(const DcmTagKey& key) const +{ + + // call base class implementation + if (SiStructuredReportingProfile::attributeRequiredIfPresent(key)) return OFTrue; + + // check additional keys required for a verification signature + if (key == DCM_SOPInstanceUID) return OFTrue; + if (key == DCM_VerificationFlag) return OFTrue; // Type 1 in SR Document General Module + if (key == DCM_VerifyingObserverSequence) return OFTrue; // Type 1C, must be present if VerificationFlag == VERIFIED + if (key == DCM_VerificationDateTime) return OFTrue; + + return OFFalse; +} + + +OFBool SiStructuredReportingVerificationProfile::checkRequiredAttributeList(DcmAttributeTag& tagList) const +{ + OFBool result = SiStructuredReportingProfile::checkRequiredAttributeList(tagList); + + result = result && + containsTag(tagList, DCM_SOPInstanceUID) && + containsTag(tagList, DCM_VerificationFlag) && + containsTag(tagList, DCM_VerifyingObserverSequence); + + // The wording in DICOM part 15 seems to indicate that ObservationDateTime + // must also be signed unconditionally. However, ObservationDateTime is actually + // an attribute within the VerifyingObserverSequence and will thus not be listed + // explicitly in tagList. + + return result; +} + + +OFCondition SiStructuredReportingVerificationProfile::inspectSignatureDataset(DcmItem & item) +{ + DcmElement *delem; + OFString s; + + // check if this is an SR document by looking up the most important + // attributes we expect in any SR document + if (item.findAndGetElement(DCM_ValueType, delem).good() && + item.findAndGetElement(DCM_ConceptNameCodeSequence, delem).good() && + item.findAndGetElement(DCM_ContentSequence, delem).good()) + { + // fine, this is an SR document + if (item.findAndGetOFString(DCM_VerificationFlag, s).bad() || (s != "VERIFIED")) + { + // SR document status is not 'VERIFIED', cannot apply SR RSA Digital Signature Profile verification signature + return SI_EC_DatasetDoesNotMatchProfile; + } + return EC_Normal; + } + else + { + // not an SR document + return SI_EC_DatasetDoesNotMatchProfile; + } +} + +SiSignaturePurpose::E_SignaturePurposeType SiStructuredReportingVerificationProfile::getOverrideSignaturePurpose() const +{ + return SiSignaturePurpose::ESP_VerificationSignature; +} + +#else /* WITH_OPENSSL */ + +int sisrvpr_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/sitsfs.cc b/dcmsign/libsrc/sitsfs.cc new file mode 100644 index 00000000..049feac4 --- /dev/null +++ b/dcmsign/libsrc/sitsfs.cc @@ -0,0 +1,226 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiTimeStamp + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sitsfs.h" +#include "dcmtk/dcmdata/dcerror.h" /* for EC_IllegalCall */ +#include "dcmtk/dcmdata/dcfilefo.h" /* for class DcmFileFormat */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_DigitalSignatureUID */ + +BEGIN_EXTERN_C +#include +#include +END_EXTERN_C + + + +SiTimeStampFS::SiTimeStampFS() +: SiTimeStamp() +, tsqFilename_() +, tsrFilename_() +, uidFilename_() +{ +} + + +SiTimeStampFS::~SiTimeStampFS() +{ +} + + +void SiTimeStampFS::setTSQFilename(const char *fname) +{ + if (fname) + tsqFilename_ = fname; + else tsqFilename_ = ""; +} + + +void SiTimeStampFS::setTSRFilename(const char *fname) +{ + if (fname) + tsrFilename_ = fname; + else tsrFilename_ = ""; +} + + +void SiTimeStampFS::setUIDFilename(const char *fname) +{ + if (fname) + uidFilename_ = fname; + else uidFilename_ = ""; +} + + +OFCondition SiTimeStampFS::stamp( + const unsigned char *inputData, + unsigned long inputDataSize) +{ + return create_ts_query(inputData, inputDataSize); +} + + +OFCondition SiTimeStampFS::write(DcmItem& item) +{ + + TS_REQ *query = getTSQ(); + if (query == NULL) + { + DCMSIGN_ERROR("No timestamp query object available, cannot write to file."); + return EC_IllegalCall; + } + + OFCondition result = EC_Normal; + + // first we write the time stamp query file + if (tsqFilename_.length() == 0) + { + DCMSIGN_WARN("Name of timestamp query file not set, will not write file."); + } + else + { + BIO *out_bio = BIO_new_file(tsqFilename_.c_str(), "wb"); + if (out_bio == NULL) + { + DCMSIGN_WARN("Unable to create time stamp query file '" << tsqFilename_ << "'"); + result = SI_EC_CannotWriteTSQ; + } + else + { + if (!i2d_TS_REQ_bio(out_bio, query)) + { + DCMSIGN_WARN("Writing time stamp query file '" << tsqFilename_ << "' failed"); + result = SI_EC_CannotWriteTSQ; + } + BIO_free_all(out_bio); + } + } + + if (result.bad()) return result; + + // now we write the UID file + if (uidFilename_.length() == 0) + { + DCMSIGN_WARN("Name of UID file for time stamp query not set, will not write file."); + } + else + { + OFString uid; + DcmFileFormat dfile; + if (item.findAndGetOFString(DCM_DigitalSignatureUID, uid).good()) + { + result = dfile.getDataset()->putAndInsertString(DCM_DigitalSignatureUID, uid.c_str()); + if (result.good()) result = dfile.saveFile(uidFilename_, EXS_LittleEndianImplicit); + } + else + { + DCMSIGN_ERROR("Signature UID not found in dataset."); + result = EC_IllegalCall; + } + } + + return result; +} + + +OFCondition SiTimeStampFS::getUIDFromFile(OFString& uid) +{ + if (uidFilename_.length() == 0) + { + DCMSIGN_ERROR("Cannot load UID file, filename not set"); + return EC_IllegalCall; + } + + DcmFileFormat dfile; + OFCondition result = dfile.loadFile(uidFilename_); + if (result.good()) + { + result = dfile.getDataset()->findAndGetOFString(DCM_DigitalSignatureUID, uid); + if (result.bad()) DCMSIGN_ERROR("No Digital Signature UID found in UID file '" << uidFilename_ << "'"); + } + else + { + DCMSIGN_ERROR("Cannot load UID file '" << uidFilename_ << "'"); + } + + return result; +} + + +OFCondition SiTimeStampFS::load_ts_query_from_file() +{ + if (tsqFilename_.length() == 0) + { + DCMSIGN_ERROR("Cannot load timestamp query file, filename not set"); + return EC_IllegalCall; + } + + return SiTimeStamp::load_ts_query(tsqFilename_.c_str()); +} + + +OFCondition SiTimeStampFS::load_ts_response_from_file() +{ + if (tsrFilename_.length() == 0) + { + DCMSIGN_ERROR("Cannot load timestamp response file, filename not set"); + return EC_IllegalCall; + } + + return SiTimeStamp::load_ts_response(tsrFilename_.c_str()); +} + + +OFCondition SiTimeStampFS::check_ts_response(DcmItem& ditem) +{ + if (getTSQ() == NULL) + { + DCMSIGN_ERROR("Cannot check timestamp response, timestamp query not loaded"); + return EC_IllegalCall; + } + + if (getTSR() == NULL) + { + DCMSIGN_ERROR("Cannot check timestamp response, not loaded"); + return EC_IllegalCall; + } + + return SiTimeStamp::check_ts_response(getTSQ(), getTSR(), ditem); + +} + + +OFCondition SiTimeStampFS::write_ts_token(DcmItem& ditem) +{ + return SiTimeStamp::write_ts_token(getTSR(), ditem); +} + + + +#else /* WITH_OPENSSL */ + +int sitsfs_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/sitstamp.cc b/dcmsign/libsrc/sitstamp.cc new file mode 100644 index 00000000..ab6a524c --- /dev/null +++ b/dcmsign/libsrc/sitstamp.cc @@ -0,0 +1,1390 @@ +/* + * + * Copyright (C) 2019, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsign + * + * Author: Marco Eichelberg + * + * Purpose: + * classes: SiTimeStamp + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_OPENSSL + +#include "dcmtk/dcmsign/sitstamp.h" + +#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmsign/simd5.h" +#include "dcmtk/dcmsign/siripemd.h" +#include "dcmtk/dcmsign/sisha1.h" +#include "dcmtk/dcmsign/sisha256.h" +#include "dcmtk/dcmsign/sisha384.h" +#include "dcmtk/dcmsign/sisha512.h" +#include "dcmtk/dcmsign/sicert.h" +#include "dcmtk/dcmsign/sicertvf.h" +#include "dcmtk/dcmsign/dcsignat.h" +#include "dcmtk/ofstd/ofdatime.h" + +BEGIN_EXTERN_C +#include +#include +#include +#include +#include +END_EXTERN_C + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +#define X509_get0_notBefore(x) X509_get_notBefore(x) +#define X509_get0_notAfter(x) X509_get_notAfter(x) +#define TS_STATUS_INFO_get0_status(x) (x)->status +#define TS_STATUS_INFO_get0_text(x) (x)->text +#define TS_STATUS_INFO_get0_failure_info(x) (x)->failure_info +#define TS_VERIFY_CTS_set_certs(x,y) ((x)->certs = (y)) +#define TS_VERIFY_CTX_set_data(x,y) ((x)->data = (y)) +#define TS_VERIFY_CTX_set_flags(x,y) ((x)->flags = (y)) +#define TS_VERIFY_CTX_set_store(x,y) ((x)->store = (y)) +#define ASN1_STRING_get0_data(x) ASN1_STRING_data((asn1_string_st*)x) +#endif + +/// maximum length of the integer nonce, in bytes +#define NONCE_LENGTH 8 + +/// simple RAII container class for a raw buffer +class RAIIBuffer +{ +public: + /** constructor, allocates buffer + * @param len buffer size, must be > 0 + */ + RAIIBuffer(size_t len) + : buf_(new unsigned char[len]) + , len_(len) + { + } + + /// destructor + virtual ~RAIIBuffer() + { + delete[] buf_; + } + + /// buffer + unsigned char *buf_; + + /// buffer size + size_t len_; +}; + + +SiTimeStamp::SiTimeStamp() +: tsq_policy_() +, tsq_mac_(EMT_SHA256) +, tsq_use_nonce_(OFTrue) +, tsq_certificate_requested_(OFTrue) +, tsq_(NULL) +, tsr_(NULL) +, ts_(NULL) +, tsinfo_(NULL) +, errorCode_(0) +, errorString_("") +{ +} + + +SiTimeStamp::~SiTimeStamp() +{ + TS_REQ_free(tsq_); + TS_RESP_free(tsr_); + PKCS7_free(ts_); + TS_TST_INFO_free(tsinfo_); +} + +void SiTimeStamp::setPolicyOID(const char *oid) +{ + if (oid) tsq_policy_ = oid; else tsq_policy_ = ""; +} + + +void SiTimeStamp::setNonce(OFBool nonce) +{ + tsq_use_nonce_ = nonce; +} + + +void SiTimeStamp::setCertificateRequested(OFBool creq) +{ + tsq_certificate_requested_ = creq; +} + +void SiTimeStamp::setMAC(E_MACType mac) +{ + tsq_mac_ = mac; +} + + +OFCondition SiTimeStamp::create_ts_query( + const unsigned char *inputData, + unsigned long inputDataSize) +{ + + // validate input parameters + if (inputData == NULL || inputDataSize == 0) return EC_IllegalCall; + + // delete a previous time stamp query, if present + if (tsq_) + { + TS_REQ_free(tsq_); + tsq_ = NULL; + } + + // create message digest object + SiMAC *mac = NULL; // dcmsign MAC object + const EVP_MD *evpmd = NULL; // OpenSSL MAC object + switch (tsq_mac_) + { + case EMT_SHA1: + mac = new SiSHA1(); + evpmd = EVP_sha1(); + break; + case EMT_RIPEMD160: + mac = new SiRIPEMD160(); + evpmd = EVP_ripemd160(); + break; + case EMT_MD5: + mac = new SiMD5(); + evpmd = EVP_md5(); + break; + case EMT_SHA256: + mac = new SiSHA256(); + evpmd = EVP_sha256(); + break; + case EMT_SHA384: + mac = new SiSHA384(); + evpmd = EVP_sha384(); + break; + case EMT_SHA512: + mac = new SiSHA512(); + evpmd = EVP_sha512(); + break; + default: + DCMSIGN_WARN("Unsupported MAC algorithm for timestamp selected."); + return SI_EC_UnsupportedMAC; + break; + } + if (mac == NULL || evpmd == NULL) return EC_MemoryExhausted; + + // compute message digest + OFCondition result = EC_Normal; + RAIIBuffer md(mac->getSize()); + result = mac->initialize(); + if (result.good()) result = mac->digest(inputData, inputDataSize); + if (result.good()) result = mac->finalize(md.buf_); + + // delete message digest object + delete mac; + + if (result.good()) + { + // create time stamp request, algorithm and message imprint objects + tsq_ = TS_REQ_new(); + X509_ALGOR *algo = X509_ALGOR_new(); + TS_MSG_IMPRINT *msg_imprint = TS_MSG_IMPRINT_new(); + if (tsq_ && algo && msg_imprint) + { + // set time stamp query version (always 1) + if (!TS_REQ_set_version(tsq_, 1)) result = SI_EC_OpenSSLFailure; + + // set message digest type + if (result.good()) + { + if (NULL == (algo->algorithm = OBJ_nid2obj(EVP_MD_type(evpmd)))) result = SI_EC_OpenSSLFailure; + } + + // create parameter object + if (result.good()) + { + if (NULL == (algo->parameter = ASN1_TYPE_new())) result = EC_MemoryExhausted; + } + + // copy algorithm object into message imprint + if (result.good()) + { + algo->parameter->type = V_ASN1_NULL; + if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo)) result = SI_EC_OpenSSLFailure; + } + + // copy message digest into message imprint + if (result.good()) + { + if (!TS_MSG_IMPRINT_set_msg(msg_imprint, md.buf_, OFstatic_cast(int, md.len_))) result = SI_EC_OpenSSLFailure; + } + + // copy message imprint into time stamp query + if (result.good()) + { + if (!TS_REQ_set_msg_imprint(tsq_, msg_imprint)) result = SI_EC_OpenSSLFailure; + } + + // set certificate requested flag + if (result.good()) + { + if (!TS_REQ_set_cert_req(tsq_, (tsq_certificate_requested_ ? 1: 0))) result = SI_EC_OpenSSLFailure; + } + } + else result = EC_MemoryExhausted; + + // delete algorithm object + X509_ALGOR_free(algo); + + // delete message imprint object + TS_MSG_IMPRINT_free(msg_imprint); + + // now we check the optional components of a time stamp query + + // policy OID + if (result.good() && (tsq_policy_.length() > 0)) + { + ASN1_OBJECT *policy_obj = OBJ_txt2obj(tsq_policy_.c_str(), 0); + if (policy_obj) + { + // copy policy object into time stamp query + if (!TS_REQ_set_policy_id(tsq_, policy_obj)) result = SI_EC_OpenSSLFailure; + + // delete policy object + ASN1_OBJECT_free(policy_obj); + } + else + { + DCMSIGN_WARN("Cannot convert " << tsq_policy_ << " to OID."); + result = SI_EC_InvalidOID; + } + } + + // nonce (pseudo-random integer used as protection against replay attacks) + if (result.good() && tsq_use_nonce_) + { + // create buffer for random data + unsigned char nonce_buf[NONCE_LENGTH]; + + // fill buffer with random data + if (RAND_bytes(nonce_buf, NONCE_LENGTH) <= 0) result = SI_EC_OpenSSLFailure; + + if (result.good()) + { + // create nonce object + ASN1_INTEGER *nonce_asn1 = ASN1_INTEGER_new(); + + if (nonce_asn1) + { + // free memory buffer of nonce_asn1 (we will create a new one) + OPENSSL_free(nonce_asn1->data); + + // Find the first non-zero byte in the buffer + int i = 0; + for (i = 0; i < NONCE_LENGTH && !nonce_buf[i]; ++i) + continue; + + // create a new memory buffer for nonce_asn1 + nonce_asn1->length = NONCE_LENGTH - i; + nonce_asn1->data = OFreinterpret_cast(unsigned char *, OPENSSL_malloc(nonce_asn1->length + 1)); + if (NULL != nonce_asn1->data) + { + // copy random data into nonce. The first byte is guaranteed to be nonzero, + // which is necessary because otherwise the field might violate DER encoding. + memcpy(nonce_asn1->data, nonce_buf + i, nonce_asn1->length); + } + else result = EC_MemoryExhausted; + + if (result.good()) + { + // copy policy object into time stamp query + if (!TS_REQ_set_nonce(tsq_, nonce_asn1)) result = SI_EC_OpenSSLFailure; + } + + // delete nonce object + ASN1_INTEGER_free(nonce_asn1); + } + else result = EC_MemoryExhausted; + } + } + } + + return result; +} + +///helper structure for status bit arrays. +struct StatusMap +{ + int bit; + const char *text; +}; + +/** status flags for timestamp resonse failures + * Source: OpenSSL, ts_rsp_print.c + */ +static StatusMap failure_map[] = +{ + {TS_INFO_BAD_ALG, + "unrecognized or unsupported algorithm identifier"}, + {TS_INFO_BAD_REQUEST, + "transaction not permitted or supported"}, + {TS_INFO_BAD_DATA_FORMAT, + "the data submitted has the wrong format"}, + {TS_INFO_TIME_NOT_AVAILABLE, + "the TSA's time source is not available"}, + {TS_INFO_UNACCEPTED_POLICY, + "the requested TSA policy is not supported by the TSA"}, + {TS_INFO_UNACCEPTED_EXTENSION, + "the requested extension is not supported by the TSA"}, + {TS_INFO_ADD_INFO_NOT_AVAILABLE, + "the additional information requested could not be understood " + "or is not available"}, + {TS_INFO_SYSTEM_FAILURE, + "the request cannot be handled due to system failure"}, + {-1, NULL} +}; + +OFCondition SiTimeStamp::check_ts_response( + TS_REQ *tsq, + TS_RESP *tsr, + DcmItem& ditem) +{ + if (tsr == NULL) return EC_IllegalCall; + + // retrieve status structure from timestamp response. + // This function does not create a copy that we need to release later. + TS_STATUS_INFO *status = TS_RESP_get_status_info(tsr); + if (status == NULL) + { + DCMSIGN_ERROR("unable to access status structure of timestamp response message"); + return SI_EC_InvalidTSR; + } + + // evaluate status structure from timestamp response + OFCondition result = EC_Normal; + long status_value = ASN1_INTEGER_get(TS_STATUS_INFO_get0_status(status)); + + if (status_value != 0) // status 0 means "granted", i.e. success + { + if (status_value == 1) DCMSIGN_WARN("timestamp response status: granted with modifications"); + else + { + result = SI_EC_InvalidTSR; + switch (status_value) + { + case 2: + DCMSIGN_ERROR("timestamp response status: rejected"); + break; + case 3: + DCMSIGN_ERROR("timestamp response status: waiting"); + break; + case 4: + DCMSIGN_ERROR("timestamp response status: revocation warning"); + break; + case 5: + DCMSIGN_ERROR("timestamp response status: revoked"); + break; + default: + DCMSIGN_ERROR("timestamp response status: unknown error code " << status_value); + break; + } + } + + // if we have additional status text (optional), let's print it to the logger + const unsigned char *c = NULL; + for (int i = 0; i < sk_ASN1_UTF8STRING_num(TS_STATUS_INFO_get0_text(status)); ++i) + { + c = ASN1_STRING_get0_data(sk_ASN1_UTF8STRING_value(TS_STATUS_INFO_get0_text(status), i)); + if (c) DCMSIGN_WARN("timestamp response status text: " << c); + } + + // if we have additional failure info flags (optional), let's print them to the logger + if (TS_STATUS_INFO_get0_failure_info(status) != NULL) + { + const StatusMap *fmap = failure_map; + for (; fmap->bit >= 0; ++fmap) + { + if (ASN1_BIT_STRING_get_bit(TS_STATUS_INFO_get0_failure_info(status), fmap->bit)) + { + DCMSIGN_WARN("timestamp response status text: " << fmap->text); + } + } + } + } + + TS_TST_INFO *ts_info = NULL; + + // access TSTInfo structure (i.e. the content of the signed timestamp) + if (result.good()) + { + ts_info = TS_RESP_get_tst_info(tsr); + if (ts_info == NULL) + { + DCMSIGN_ERROR("timestamp response does not contain TSTInfo structure"); + result = SI_EC_InvalidTSR; + } + } + + // check version number of timestamp response + if (result.good()) + { + if (TS_TST_INFO_get_version(ts_info) != 1) + { + DCMSIGN_ERROR("unsupported timestamp response version number " << TS_TST_INFO_get_version(ts_info)); + result = SI_EC_InvalidTSR; + } + } + + // access TSR message imprint (MAC algorithm and hash) + TS_MSG_IMPRINT *ts_info_imprint = NULL; + if (result.good()) + { + ts_info_imprint = TS_TST_INFO_get_msg_imprint(ts_info); + if (ts_info_imprint == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: message imprint missing in timestamp response"); + result = SI_EC_InvalidTSR; + } + } + + // access TSR MAC algorithm OID + X509_ALGOR *ts_info_algo = NULL; + if (result.good()) + { + ts_info_algo = TS_MSG_IMPRINT_get_algo(ts_info_imprint); + if (ts_info_algo == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: message digest algorithm missing in timestamp response"); + result = SI_EC_InvalidTSR; + } + } + + // bail out if the timestamp response had an error status + if (result.bad()) return result; + + // check if the timestamp response matches the timestamp query + if (tsq == NULL) + { + DCMSIGN_WARN("timestamp query not available, will not check consistency with timestamp response"); + } + else + { + // at this point, tsq and ts_info are guaranteed to be valid pointers. + + // access message imprints (MAC algorithm and hash) + TS_MSG_IMPRINT *tsq_imprint = TS_REQ_get_msg_imprint(tsq); + if (tsq_imprint) + { + // compare message imprints + X509_ALGOR *tsq_algo = TS_MSG_IMPRINT_get_algo(tsq_imprint); + if (tsq_algo == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: message digest algorithm missing in timestamp query"); + result = SI_EC_InvalidTSR; + } + else + { + if (OBJ_cmp(tsq_algo->algorithm, ts_info_algo->algorithm)) + { + DCMSIGN_ERROR("timestamp response validation failed: message digest algorithms are different in timestamp query and response"); + result = SI_EC_InvalidTSR; + } + else + { + unsigned int tsq_len = ASN1_STRING_length(TS_MSG_IMPRINT_get_msg(tsq_imprint)); + unsigned int ts_info_len = ASN1_STRING_length(TS_MSG_IMPRINT_get_msg(ts_info_imprint)); + if (tsq_len != ts_info_len) + { + DCMSIGN_ERROR("timestamp response validation failed: message digest lengths are different in timestamp query and response"); + result = SI_EC_InvalidTSR; + } + else + { + if (memcmp(ASN1_STRING_get0_data(TS_MSG_IMPRINT_get_msg(tsq_imprint)), + ASN1_STRING_get0_data(TS_MSG_IMPRINT_get_msg(ts_info_imprint)), tsq_len) != 0) + { + DCMSIGN_ERROR("timestamp response validation failed: message digests do not match in timestamp query and response"); + result = SI_EC_InvalidTSR; + } + } + } + } + } + else + { + DCMSIGN_ERROR("timestamp response validation failed: message imprint missing in timestamp query"); + result = SI_EC_InvalidTSR; + } + if (result.bad()) return result; + + // check nonces for consistency + const ASN1_INTEGER *tsq_nonce = TS_REQ_get_nonce(tsq); + if (tsq_nonce) // the timestamp query may or may not contain a nonce + { + // query contains a nonce, therefore, the response MUST also contain a nonce + // with the same value + const ASN1_INTEGER *ts_info_nonce = TS_TST_INFO_get_nonce(ts_info); + if (ts_info_nonce == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: nonce is missing in timestamp response"); + result = SI_EC_InvalidTSR; + } + else + { + // compare nonces + if (ASN1_INTEGER_cmp(tsq_nonce, ts_info_nonce) != 0) + { + DCMSIGN_ERROR("timestamp response validation failed: nonces are not equal in timestamp query and response"); + result = SI_EC_InvalidTSR; + } + } + } + if (result.bad()) return result; + + // check policy OIDs for consistency + ASN1_OBJECT *tsq_policy = TS_REQ_get_policy_id(tsq); + if (tsq_policy) // the timestamp query may or may not contain a policy OID + { + const ASN1_OBJECT *ts_info_policy = TS_TST_INFO_get_policy_id(ts_info); + if (ts_info_policy == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: policy OID is missing in timestamp response"); + result = SI_EC_InvalidTSR; + } + else + { + // compare policy OIDs + if (OBJ_cmp(tsq_policy, ts_info_policy) != 0) + { + DCMSIGN_ERROR("timestamp response validation failed: policy OIDs are not equal in timestamp query and response"); + result = SI_EC_InvalidTSR; + } + } + } + if (result.bad()) return result; + } + + // the timestamp response looks OK and is consistent with the timestamp query; + // now let's check consistency with the DICOM signature. + + // get the signature from the DICOM dataset + const Uint8 *signature = NULL; + unsigned long sigLength = 0; + result = ditem.findAndGetUint8Array(DCM_Signature, signature, &sigLength); + if (result.bad() || sigLength < 4 || (signature == NULL)) + { + DCMSIGN_ERROR("timestamp response validation failed: signature in DICOM dataset not found or invalid"); + result = SI_EC_InvalidTSR; + } + + // determine type of signature + E_KeyType signatureType = EKT_none; + if (result.good()) + { + SiCertificate cert; + result = cert.read(ditem); + if (result.good()) signatureType = cert.getKeyType(); + else + { + DCMSIGN_ERROR("timestamp response validation failed: certificate in DICOM dataset not found or invalid"); + result = SI_EC_InvalidTSR; + } + } + + // if the signature type is DSA or ECDSA, we need to account for a possible pad byte + if (result.good()) + { + if (signatureType == EKT_DSA || signatureType == EKT_EC) + { + DcmSignature::adjustASN1SequenceLength(signature, sigLength); + } + } + + // now determine the MAC algorithm we need to feed the signature to + SiMAC *mac = NULL; + if (result.good()) + { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + ASN1_OBJECT *mac_oid = NULL; + void *ppval = NULL; +#else + const ASN1_OBJECT *mac_oid = NULL; + const void *ppval = NULL; +#endif + int pptype = 0; + X509_ALGOR_get0(&mac_oid, &pptype, &ppval, ts_info_algo); + if (mac_oid == NULL) + { + DCMSIGN_ERROR("timestamp response validation failed: cannot determine MAC algorithm in timestamp response"); + result = SI_EC_InvalidTSR; + } + else + { + int mac_nid = OBJ_obj2nid(mac_oid); + const char *mac_name = OBJ_nid2ln(mac_nid); + switch (mac_nid) + { + case NID_sha1: + mac = new SiSHA1(); + break; + case NID_ripemd160: + mac = new SiRIPEMD160(); + break; + case NID_md5: + mac = new SiMD5(); + break; + case NID_sha256: + mac = new SiSHA256(); + break; + case NID_sha384: + mac = new SiSHA384(); + break; + case NID_sha512: + mac = new SiSHA512(); + break; + default: + DCMSIGN_ERROR("timestamp response validation failed: unsupported MAC algorithm " << ( mac_name ? mac_name : "(unknown)") << " in timestamp response"); + result = SI_EC_InvalidTSR; + break; + } + } + } + + // check that the lenghts of both MACs are really the same + if (result.good()) + { + // mac is now guaranteed to point to a valid SiMAC object + unsigned int ts_info_len = ASN1_STRING_length(TS_MSG_IMPRINT_get_msg(ts_info_imprint)); + if (mac->getSize() != ts_info_len) + { + DCMSIGN_ERROR("timestamp response validation failed: message digest length does not match in DICOM dataset and timestamp response"); + result = SI_EC_InvalidTSR; + } + } + + // compute MAC of digital signature and compare with the MAC in the TSR + if (result.good()) + { + RAIIBuffer md(mac->getSize()); + result = mac->initialize(); + if (result.good()) result = mac->digest(signature, sigLength); + if (result.good()) result = mac->finalize(md.buf_); + if (memcmp(md.buf_, ASN1_STRING_get0_data(TS_MSG_IMPRINT_get_msg(ts_info_imprint)), mac->getSize()) != 0) + { + DCMSIGN_ERROR("timestamp response validation failed: message digests do not match in DICOM dataset and timestamp response"); + result = SI_EC_InvalidTSR; + } + } + + // delete message digest object + delete mac; + + // Done. If we have found not problem at this point, the TSR is successful and matches + // both the TSQ (if present) and the DICOM dataset. + return result; +} + + +OFCondition SiTimeStamp::load_ts_query(const char *fname) +{ + if (fname == NULL) return EC_InvalidFilename; + TS_REQ_free(tsq_); + tsq_ = NULL; + + OFCondition result = EC_Normal; + BIO *in_bio = BIO_new_file(fname, "rb"); + if ((in_bio == NULL) || (NULL == (tsq_ = d2i_TS_REQ_bio(in_bio, NULL)))) + { + DCMSIGN_ERROR("Unable to load timestamp query file '" << fname << "'"); + result = SI_EC_CannotRead; + } + BIO_free_all(in_bio); + return result; +} + + +OFCondition SiTimeStamp::load_ts_response(const char *fname) +{ + if (fname == NULL) return EC_InvalidFilename; + TS_RESP_free(tsr_); + tsr_ = NULL; + + OFCondition result = EC_Normal; + BIO *in_bio = BIO_new_file(fname, "rb"); + if ((in_bio == NULL) || (NULL == (tsr_ = d2i_TS_RESP_bio(in_bio, NULL)))) + { + DCMSIGN_ERROR("Unable to load timestamp response file '" << fname << "'"); + result = SI_EC_CannotRead; + } + BIO_free_all(in_bio); + return result; +} + + +OFCondition SiTimeStamp::write_ts_token( + TS_RESP *tsr, + DcmItem& ditem) +{ + if (tsr == NULL) + { + DCMSIGN_ERROR("Cannot insert timestamp response into DICOM dataset, not loaded"); + return EC_IllegalCall; + } + + PKCS7 *ts_token = TS_RESP_get_token(tsr); + if (ts_token == NULL) + { + DCMSIGN_ERROR("No timestamp token in the timestamp respone"); + return SI_EC_InvalidTSR; + } + + // write timestamp token to buffer + OFCondition result = EC_Normal; + unsigned char *ts_token_buf = NULL; + int len = i2d_PKCS7(ts_token, &ts_token_buf); + + if (len < 0) + { + DCMSIGN_ERROR("Error while serializing timestamp token"); + result = SI_EC_OpenSSLFailure; + } + + if (result.good()) result = ditem.putAndInsertUint8Array(DCM_CertifiedTimestamp, ts_token_buf, len); + if (result.good()) result = ditem.putAndInsertString(DCM_CertifiedTimestampType, "CMS_TSP"); + + OPENSSL_free(ts_token_buf); + return result; +} + + +OFCondition SiTimeStamp::read(DcmItem& item) +{ + OFString tstype; + const Uint8 *tsbytes = NULL; + unsigned long tslen = 0; + + // delete any prior timestamp ticket + PKCS7_free(ts_); + ts_ = NULL; + TS_TST_INFO_free(tsinfo_); + tsinfo_ = NULL; + + // check certified timestamp type + OFCondition result = item.findAndGetOFString(DCM_CertifiedTimestampType, tstype); + if (result.good()) + { + if (tstype == "CMS_TSP") + { + // access certified timestamp + result = item.findAndGetUint8Array(DCM_CertifiedTimestamp, tsbytes, &tslen); + if (result.good()) + { + // adjust for a possible pad byte + DcmSignature::adjustASN1SequenceLength(tsbytes, tslen); + const unsigned char *tsbytes_temp = tsbytes; + ts_ = d2i_PKCS7(NULL, &tsbytes_temp, tslen); + if (ts_ == NULL) + { + DCMSIGN_WARN("unable to read certified timestamp in dataset"); + result = SI_EC_InvalidTimestamp; + } + else + { + // PKCS7_to_TS_TST_INFO() is an "expensive" function that parses + // the content of the signed timestamp ticket. Therefore, we cache + // the result. + tsinfo_ = PKCS7_to_TS_TST_INFO(ts_); + if (tsinfo_ == NULL) + { + DCMSIGN_WARN("unable to read certified timestamp ticket in dataset"); + result = SI_EC_InvalidTimestamp; + } + } + } + } + else + { + DCMSIGN_WARN("unknown certified timestamp type: " << tstype); + result = SI_EC_UnknownTimestampType; + } + } + return result; +} + + +OFBool SiTimeStamp::have_tsinfo() const +{ + return (tsinfo_ != NULL); +} + +long SiTimeStamp::get_tsinfo_version() const +{ + if (tsinfo_) + return TS_TST_INFO_get_version(tsinfo_); + else return -1; +} + + +void SiTimeStamp::get_tsinfo_policy_oid(OFString& oid) const +{ +#define TSINFO_BUFSIZE 200 + oid = ""; + if (tsinfo_) + { + char buf[TSINFO_BUFSIZE]; // The OpenSSL recommends a buffer of at least 80 characters + buf[0]='\0'; // zero terminate buffer + int len = OBJ_obj2txt(buf, TSINFO_BUFSIZE, TS_TST_INFO_get_policy_id(tsinfo_), 1); + if (len > TSINFO_BUFSIZE) + { + DCMSIGN_WARN("timestamp policy OID truncated, length is " << len); + } + oid = buf; + } +} + + +void SiTimeStamp::get_tsinfo_imprint_algorithm_name(OFString& mac) const +{ + mac = ""; + if (tsinfo_) + { + + TS_MSG_IMPRINT *ts_info_imprint = TS_TST_INFO_get_msg_imprint(tsinfo_); + if (ts_info_imprint == NULL) + { + DCMSIGN_WARN("timestamp imprint cannot be accessed"); + } + else + { + X509_ALGOR *ts_info_algo = TS_MSG_IMPRINT_get_algo(ts_info_imprint); + if (ts_info_algo == NULL) + { + DCMSIGN_WARN("timestamp imprint algorithm cannot be accessed"); + } + else + { + char buf[TSINFO_BUFSIZE]; // The OpenSSL recommends a buffer of at least 80 characters + buf[0]='\0'; // zero terminate buffer + int len = OBJ_obj2txt(buf, TSINFO_BUFSIZE, ts_info_algo->algorithm, 0); + if (len > TSINFO_BUFSIZE) + { + DCMSIGN_WARN("timestamp imprint algorithm name truncated, length is " << len); + } + mac = buf; + } + } + } +} + + +void SiTimeStamp::get_tsinfo_serial_number(OFString& serial) const +{ + serial = ""; + if (tsinfo_) + { + const ASN1_INTEGER *asn1serial = TS_TST_INFO_get_serial(tsinfo_); + if (asn1serial == NULL) + { + DCMSIGN_WARN("timestamp serial number cannot be accessed"); + } + else + { + BIGNUM *bnserial = ASN1_INTEGER_to_BN(asn1serial, NULL); // creates new object + if (bnserial == NULL) + { + DCMSIGN_WARN("timestamp serial number cannot be converted to BIGNUM"); + } + else + { + BIO *bio = BIO_new(BIO_s_mem()); + if (bio) + { + char *bufptr = NULL; + BN_print(bio, bnserial); + BIO_write(bio,"\0",1); // add terminating zero + BIO_get_mem_data(bio, (char *)(&bufptr)); + if (bufptr) + { + serial = "0x"; + serial += bufptr; + } + BIO_free(bio); + } + else + { + DCMSIGN_WARN("timestamp serial number cannot be printed"); + } + BN_free(bnserial); + } + } + } +} + + +void SiTimeStamp::get_tsinfo_nonce(OFString& nonce) const +{ + nonce = ""; + if (tsinfo_) + { + const ASN1_INTEGER *asn1nonce = TS_TST_INFO_get_nonce(tsinfo_); + if (asn1nonce) // nonce is an optional field, may be absent + { + BIGNUM *bnnonce = ASN1_INTEGER_to_BN(asn1nonce, NULL); // creates new object + if (bnnonce == NULL) + { + DCMSIGN_WARN("timestamp nonce cannot be converted to BIGNUM"); + } + else + { + BIO *bio = BIO_new(BIO_s_mem()); + if (bio) + { + char *bufptr = NULL; + BN_print(bio, bnnonce); + BIO_write(bio,"\0",1); // add terminating zero + BIO_get_mem_data(bio, (char *)(&bufptr)); + if (bufptr) + { + nonce = "0x"; + nonce += bufptr; + } + BIO_free(bio); + } + else + { + DCMSIGN_WARN("timestamp nonce cannot be printed"); + } + BN_free(bnnonce); + } + } + } +} + + +void SiTimeStamp::get_tsinfo_tsa_name(OFString& tsa) const +{ + tsa = ""; + if (tsinfo_) + { + GENERAL_NAME *tsaname = TS_TST_INFO_get_tsa(tsinfo_); + if (tsaname) // tsa is an optional field, may be absent + { + BIO *bio = BIO_new(BIO_s_mem()); + if (bio) + { + char *bufptr = NULL; + GENERAL_NAME_print(bio, tsaname); + BIO_write(bio,"\0",1); // add terminating zero + BIO_get_mem_data(bio, (char *)(&bufptr)); + if (bufptr) + { + tsa = bufptr; + } + BIO_free(bio); + } + else + { + DCMSIGN_WARN("timestamp tsa cannot be printed"); + } + } + } +} + + +void SiTimeStamp::get_tsinfo_accuracy(OFString& accuracy) const +{ + accuracy = ""; + if (tsinfo_) + { + TS_ACCURACY *acc = TS_TST_INFO_get_accuracy(tsinfo_); + if (acc) // accuracy is an optional field, may be absent + { + char buf[20]; + long sec = ASN1_INTEGER_get(TS_ACCURACY_get_seconds(acc)); + long msec = ASN1_INTEGER_get(TS_ACCURACY_get_millis(acc)); + long usec = ASN1_INTEGER_get(TS_ACCURACY_get_micros(acc)); + + if (sec >= 0) + { + OFStandard::snprintf(buf, 20, "%ld", sec); + accuracy = buf; + if (usec > 0) + { + OFStandard::snprintf(buf, 20, ".%03ld%03lds", msec, usec); + accuracy += buf; + } + else + { + OFStandard::snprintf(buf, 20, ".%03lds", msec); + accuracy += buf; + } + } + } + } +} + + +OFBool SiTimeStamp::get_tsinfo_ordering() const +{ + OFBool result = OFFalse; // the default + if (tsinfo_) + { + result = TS_TST_INFO_get_ordering(tsinfo_) ? OFTrue : OFFalse; + } + return result; +} + + +void SiTimeStamp::get_tsinfo_timestamp(OFString& ts) const +{ + ts = ""; + if (tsinfo_) + { + const ASN1_GENERALIZEDTIME *gtime = TS_TST_INFO_get_time(tsinfo_); + if (gtime == NULL) + { + DCMSIGN_WARN("timestamp date/time cannot be accessed"); + } + else + { + // ASN1_GENERALIZEDTIME is just an alias for ASN1_STRING, + // so we can use ASN1_STRING_get0_data() to access the raw string + const unsigned char *c = ASN1_STRING_get0_data(gtime); + if (c) ts = OFreinterpret_cast(const char *, c); + } + } +} + +int SiTimeStamp::get_tsinfo_numextensions() const +{ + int result = 0; + if (tsinfo_) + { + result = TS_TST_INFO_get_ext_count(tsinfo_); + } + return result; +} + + +void SiTimeStamp::get_tsinfo_extension(OFString& ext, int idx) const +{ + ext = ""; + if (tsinfo_) + { + int numextensions = TS_TST_INFO_get_ext_count(tsinfo_); + if (idx >= numextensions) + { + DCMSIGN_WARN("timestamp extension " << idx << " does not exist"); + } + else + { + X509_EXTENSION *x509ext = TS_TST_INFO_get_ext(tsinfo_, idx); + if (x509ext == NULL) + { + DCMSIGN_WARN("timestamp extension " << idx << " cannot be accessed"); + } + else + { + BIO *bio = BIO_new(BIO_s_mem()); + if (bio) + { + char *bufptr = NULL; + X509V3_EXT_print(bio, x509ext, X509V3_EXT_PARSE_UNKNOWN, 0 /* indent */); + BIO_write(bio,"\0",1); // add terminating zero + BIO_get_mem_data(bio, (char *)(&bufptr)); + if (bufptr) + { + ext = bufptr; + } + BIO_free(bio); + } + else + { + DCMSIGN_WARN("timestamp extension " << idx << " cannot be printed"); + } + } + } + } +} + + +OFCondition SiTimeStamp::verifyTSSignature(SiCertificateVerifier& cv) +{ + // check if we have a timestamp object + if (ts_ == NULL) return EC_IllegalCall; + + X509 *signerCert = NULL; + OFCondition result = EC_Normal; + OFString aString; + errorCode_ = 0; + + // unfortunately, TS_RESP_verify_signature() only returns the certificate of the timestamp signer + // if the signature verification succeeds. If verification fails, e.g. because the timestamp + // certificate has expired, we have no way of accessing it + if (! TS_RESP_verify_signature(ts_, cv.getUntrustedCerts(), cv.getTrustedCertStore(), &signerCert)) + { + result = SI_EC_TimestampSignatureVerificationFailed; + errorCode_ = ERR_get_error(); + } + + if (result.good() && signerCert) + { + // compare timestamp against validity period of the TSA certificate + // The timestamp should have been created while the certificate is valid. + const ASN1_TIME *notBefore = X509_get0_notBefore(signerCert); + const ASN1_TIME *notAfter = X509_get0_notAfter(signerCert); + const ASN1_GENERALIZEDTIME *gtime = TS_TST_INFO_get_time(tsinfo_); + + OFDateTime dt_notBefore; + OFDateTime dt_notAfter; + OFDateTime dt_gtime; + + if ((notBefore == NULL)||(notAfter == NULL)||(gtime == NULL)|| + SiCertificate::convertASN1Time(notBefore, dt_notBefore).bad() || + SiCertificate::convertASN1Time(notAfter, dt_notAfter).bad() || + SiCertificate::convertGeneralizedTime(gtime, dt_gtime).bad()) + { + errorCode_ = -1; + errorString_ = "comparison of timestamp date/time with TSA certificate notBefore/notAfter attribute failed, value possibly malformed."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + else + { + if (dt_gtime < dt_notBefore) + { + errorCode_ = -1; + errorString_ = "timestamp created before start of TSA certificate validity."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + else if (dt_gtime > dt_notAfter) + { + errorCode_ = -1; + errorString_ = "timestamp created after expiry of TSA certificate."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + } + } + + // wrap certificate into a SiCertificate instance that will also free + // the memory when it goes out of scope. + // SiCertificate gracefully handles the case where signerCert is NULL. + SiCertificate cert(signerCert); + + if (signerCert && dcmsignLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) + { + DCMSIGN_INFO(" Timestamp signature certificate: "); + if ((signerCert == NULL)||(cert.getKeyType()==EKT_none)) + DCMSIGN_INFO(" none"); + else + { + DCMSIGN_INFO(" X.509v" << cert.getX509Version()); + cert.getCertSubjectName(aString); + DCMSIGN_INFO(" Subject : " << aString); + cert.getCertIssuerName(aString); + DCMSIGN_INFO(" Issued by : " << aString); + DCMSIGN_INFO(" Serial no. : " << cert.getCertSerialNo()); + cert.getCertValidityNotBefore(aString); + DCMSIGN_INFO(" Validity : not before " << aString); + cert.getCertValidityNotAfter(aString); + DCMSIGN_INFO(" Validity : not after " << aString); + const char *ecname = NULL; + switch (cert.getKeyType()) + { + case EKT_RSA: + DCMSIGN_INFO(" Public key : RSA, " << cert.getCertKeyBits() << " bits"); + break; + case EKT_DSA: + DCMSIGN_INFO(" Public key : DSA, " << cert.getCertKeyBits() << " bits"); + break; + case EKT_EC: + ecname = cert.getCertCurveName(); + if (ecname) + { + DCMSIGN_INFO(" Public key : EC, curve " << ecname << ", " << cert.getCertKeyBits() << " bits"); + } + else + { + DCMSIGN_INFO(" Public key : EC, " << cert.getCertKeyBits() << " bits"); + } + break; + case EKT_DH: + DCMSIGN_INFO(" Public key : DH, " << cert.getCertKeyBits() << " bits"); + break; + default: + case EKT_none: // should never happen + DCMSIGN_INFO(" Public key : unknown type"); + break; + } + } + } + return result; +} + + +OFCondition SiTimeStamp::verifyTSToken( + SiCertificateVerifier& cv, + DcmItem& ditem, + SiCertificate& cert) +{ + // check if we have a timestamp object + if (ts_ == NULL) return EC_IllegalCall; + + OFCondition result = EC_Normal; + errorCode_ = 0; + + // determine type of signature + E_KeyType signatureType = cert.getKeyType(); + + // create timestamp verification context + TS_VERIFY_CTX *ctx = TS_VERIFY_CTX_new(); + + if (ctx) + { + // these are the checks we want to perform + TS_VERIFY_CTX_set_flags(ctx, TS_VFY_VERSION | TS_VFY_SIGNER | TS_VFY_DATA | TS_VFY_SIGNATURE); + + // get the signature from the DICOM dataset + const Uint8 *signature = NULL; + unsigned long sigLength = 0; + result = ditem.findAndGetUint8Array(DCM_Signature, signature, &sigLength); + if (result.bad() || sigLength < 4 || (signature == NULL)) + { + DCMSIGN_ERROR("timestamp verification failed: signature in DICOM dataset not found or invalid"); + result = SI_EC_TimestampSignatureVerificationFailed; + } + + // if the signature type is DSA or ECDSA, we need to account for a possible pad byte + if (result.good()) + { + if (signatureType == EKT_DSA || signatureType == EKT_EC) + { + DcmSignature::adjustASN1SequenceLength(signature, sigLength); + } + } + + if (result.good()) + { + +#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) + BIO *bio = BIO_new_mem_buf(OFconst_cast(Uint8 *, signature), sigLength); +#else + BIO *bio = BIO_new_mem_buf(signature, sigLength); +#endif + if (bio) + { + // set the digital signature as the raw data against which + // the imprint in the timestamp ticket should be checked + TS_VERIFY_CTX_set_data(ctx, bio); + + // set certificate store and stack. Needed to verify that + // the TSA field in the timestamp ticket matches the signer certificate + TS_VERIFY_CTX_set_store(ctx, cv.getTrustedCertStore()); + TS_VERIFY_CTS_set_certs(ctx, cv.getUntrustedCerts()); + + // run the verification function + if (! TS_RESP_verify_token(ctx, ts_)) + { + result = SI_EC_TimestampSignatureVerificationFailed; + errorCode_ = ERR_get_error(); + } + + BIO_free(bio); + } + else + { + errorCode_ = -1; + errorString_ = "timestamp verification failed: cannot create memory buffer"; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + } + + // prevent TS_VERIFY_CTX_free from double-deleting our objects + TS_VERIFY_CTX_set_data(ctx, NULL); + TS_VERIFY_CTX_set_store(ctx, NULL); + TS_VERIFY_CTS_set_certs(ctx, NULL); + + TS_VERIFY_CTX_free(ctx); + } + + if (result.good()) + { + // compare timestamp against validity period of the certificate + // for the DICOM signature. The timestamp should have been created while the + // certificate is valid. + X509 *rawcert = cert.getRawCertificate(); + const ASN1_TIME *notBefore = X509_get0_notBefore(rawcert); + const ASN1_TIME *notAfter = X509_get0_notAfter(rawcert); + const ASN1_GENERALIZEDTIME *gtime = TS_TST_INFO_get_time(tsinfo_); + + OFDateTime dt_notBefore; + OFDateTime dt_notAfter; + OFDateTime dt_gtime; + + if ((notBefore == NULL)||(notAfter == NULL)||(gtime == NULL)|| + SiCertificate::convertASN1Time(notBefore, dt_notBefore).bad() || + SiCertificate::convertASN1Time(notAfter, dt_notAfter).bad() || + SiCertificate::convertGeneralizedTime(gtime, dt_gtime).bad()) + { + errorCode_ = -1; + errorString_ = "comparison of timestamp date/time with signer certificate notBefore/notAfter attribute failed, value possibly malformed."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + else + { + if (dt_gtime < dt_notBefore) + { + errorCode_ = -1; + errorString_ = "timestamp created before start of signer certificate validity."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + else if (dt_gtime > dt_notAfter) + { + errorCode_ = -1; + errorString_ = "timestamp created after expiry of signer certificate."; + DCMSIGN_ERROR(errorString_); + result = SI_EC_TimestampSignatureVerificationFailed; + } + } + } + + return result; +} + + +void SiTimeStamp::lastError(OFString& err) const +{ + if (errorCode_ < 0) err = errorString_; + else + { + const char *c = ERR_reason_error_string(errorCode_); + if (c) err = c; else err = ""; + } +} + + +#else /* WITH_OPENSSL */ + +int sitstamp_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmsign/libsrc/sitypes.cc b/dcmsign/libsrc/sitypes.cc index 96a89157..774b8ec1 100644 --- a/dcmsign/libsrc/sitypes.cc +++ b/dcmsign/libsrc/sitypes.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1998-2018, OFFIS e.V. + * Copyright (C) 1998-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -42,8 +42,27 @@ makeOFConditionConst(SI_EC_VerificationFailed_NoSignature, OFM_dcmsi makeOFConditionConst(SI_EC_VerificationFailed_UnsupportedMACAlgorithm, OFM_dcmsign, 13, OF_error, "signature verification failed: MAC algorithm not supported"); makeOFConditionConst(SI_EC_VerificationFailed_Corrupted, OFM_dcmsign, 14, OF_error, "signature verification failed: signature is invalid (document corrupted)"); makeOFConditionConst(SI_EC_VerificationFailed_NoTrust, OFM_dcmsign, 16, OF_error, "signature verification failed: certificate issued by unknown CA"); +makeOFConditionConst(SI_EC_DatasetDoesNotMatchProfile, OFM_dcmsign, 17, OF_error, "dataset not suitable for the selected security profile"); +makeOFConditionConst(SI_EC_UnsupportedMAC, OFM_dcmsign, 18, OF_error, "unsupported MAC algorithm selected"); +makeOFConditionConst(SI_EC_InvalidOID, OFM_dcmsign, 19, OF_error, "invalid object identifier (OID) string"); +makeOFConditionConst(SI_EC_CannotWriteTSQ, OFM_dcmsign, 20, OF_error, "unable to write time stamp query file"); +makeOFConditionConst(SI_EC_InvalidTSR, OFM_dcmsign, 21, OF_error, "verification of timestamp response message failed"); +makeOFConditionConst(SI_EC_VerificationFailed_NoDataElementsSigned, OFM_dcmsign, 22, OF_error, "signature verification failed: DataElementsSigned missing or incorrect"); +makeOFConditionConst(SI_EC_DataElementsSignedDoesNotMatchProfile, OFM_dcmsign, 23, OF_error, "list of data elements signed does not match profile requirements"); +makeOFConditionConst(SI_EC_ItemLocationNotFound, OFM_dcmsign, 24, OF_error, "desired signature location not found"); +makeOFConditionConst(SI_EC_UnknownTimestampType, OFM_dcmsign, 25, OF_error, "unknown certified timestamp type"); +makeOFConditionConst(SI_EC_InvalidTimestamp, OFM_dcmsign, 26, OF_error, "certified timestamp in dataset cannot be read"); +makeOFConditionConst(SI_EC_InvalidFiletype, OFM_dcmsign, 27, OF_error, "filetype is unknown (neither PEM nor DER)"); +makeOFConditionConst(SI_EC_TimestampSignatureVerificationFailed, OFM_dcmsign, 28, OF_error, "signature verification of the certified timestamp failed"); +makeOFConditionConst(SI_EC_VerificationFailed_CertExpiredAtSignature, OFM_dcmsign, 29, OF_error, "signature verification failed: certificate was expired at signature creation date"); +makeOFConditionConst(SI_EC_VerificationFailed_CertNotYetValidAtSig, OFM_dcmsign, 30, OF_error, "signature verification failed: certificate was not yet valid at signature creation date"); +makeOFConditionConst(SI_EC_AttributeNotSignable, OFM_dcmsign, 31, OF_error, "list of attributes to be signed contains attribute that is not signable"); +makeOFConditionConst(SI_EC_VerificationFailed_AttributeNotSignable, OFM_dcmsign, 32, OF_error, "signature verification failed: signature contains attribute that is not signable"); +makeOFConditionConst(SI_EC_DatasetEmpty, OFM_dcmsign, 33, OF_error, "selected dataset or item is empty, nothing to sign"); +makeOFConditionConst(SI_EC_RequiredAttributeMissing, OFM_dcmsign, 34, OF_error, "cannot create signature for current signature profile: required attributes missing"); +makeOFConditionConst(SI_EC_EllipticCurveNotSupported, OFM_dcmsign, 35, OF_error, "cannot handle ECDSA signatures because OpenSSL was compiled without elliptic curve support"); -OFLogger DCM_dcmsignLogger = OFLog::getLogger("dcmtk.dcmsign"); +OFLogger dcmsignLogger = OFLog::getLogger("dcmtk.dcmsign"); #else /* WITH_OPENSSL */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid100.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid100.h index 17017b5d..481ff731 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid100.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid100.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID100_QuantitativeDiagnosticImagingProcedures * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:14 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:49 by J. Riesmeier * */ @@ -28,7 +28,7 @@ /** Implementation of DCMR Context Group: * CID 100 - Quantitative Diagnostic Imaging Procedures. - * (type: extensible, version: 20190121) + * (type: extensible, version: 20190817) */ class DCMTK_CMR_EXPORT CID100_QuantitativeDiagnosticImagingProcedures : public DSRContextGroup @@ -66,7 +66,7 @@ class DCMTK_CMR_EXPORT CID100_QuantitativeDiagnosticImagingProcedures PETWholeBody, /// (443271005,SCT,"PET/CT FDG imaging of whole body") PETCT_FDGImagingOfWholeBody, - /// (443844003,SCT,"PET/CT MET imaging of whole body") + /// (764704008,SCT,"PET/CT MET imaging of whole body") PETCT_METImagingOfWholeBody, /// (39142-5,LN,"CT perfusion head with contrast IV") CTPerfusionHeadWithContrastIV, diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h index b9044e1b..b30ac716 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID10013_CTAcquisitionType * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:39 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:16 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h index dc4b0209..0b7866ea 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID10033_CTReconstructionAlgorithm * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:41 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:18 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid11.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid11.h index 1a7af6e2..e71165ad 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid11.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid11.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID11_RouteOfAdministration * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:09 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:44 by J. Riesmeier * */ @@ -28,7 +28,7 @@ /** Implementation of DCMR Context Group: * CID 11 - Route of Administration. - * (type: extensible, version: 20160314) + * (type: extensible, version: 20200117) */ class DCMTK_CMR_EXPORT CID11_RouteOfAdministration : public DSRContextGroup @@ -89,7 +89,9 @@ class DCMTK_CMR_EXPORT CID11_RouteOfAdministration /// (372464004,SCT,"Intradermal route") IntradermalRoute, /// (447122006,SCT,"Intratumor route") - IntratumorRoute + IntratumorRoute, + /// (445769006,SCT,"Intracorpus cavernosum route") + IntracorpusCavernosumRoute }; /** (default) constructor diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid244.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid244.h index ac89b3c2..63a057cf 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid244.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid244.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID244_Laterality * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:16 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:51 by J. Riesmeier * */ @@ -40,9 +40,9 @@ class DCMTK_CMR_EXPORT CID244_Laterality */ enum EnumType { - /// (24028007,SCT,"Right") + /// (24028007,SCT,"Right"), included from CID 247 Right, - /// (7771000,SCT,"Left") + /// (7771000,SCT,"Left"), included from CID 247 Left, /// (51440002,SCT,"Bilateral") Bilateral, diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid29.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid29.h index c4351d39..64283184 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid29.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid29.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID29_AcquisitionModality * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:11 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:45 by J. Riesmeier * */ @@ -28,7 +28,7 @@ /** Implementation of DCMR Context Group: * CID 29 - Acquisition Modality. - * (type: extensible, version: 20190327) + * (type: extensible, version: 20201115) */ class DCMTK_CMR_EXPORT CID29_AcquisitionModality : public DSRContextGroup @@ -42,26 +42,34 @@ class DCMTK_CMR_EXPORT CID29_AcquisitionModality { /// (AR,DCM,"Autorefraction") Autorefraction, - /// (BDUS,DCM,"Ultrasound Bone Densitometry") - UltrasoundBoneDensitometry, /// (BI,DCM,"Biomagnetic Imaging") BiomagneticImaging, /// (BMD,DCM,"Bone Mineral Densitometry") BoneMineralDensitometry, + /// (EPS,DCM,"Cardiac Electrophysiology") + CardiacElectrophysiology, /// (CR,DCM,"Computed Radiography") ComputedRadiography, /// (CT,DCM,"Computed Tomography") ComputedTomography, + /// (DMS,DCM,"Dermoscopy") + Dermoscopy, /// (DG,DCM,"Diaphanography") Diaphanography, /// (DX,DCM,"Digital Radiography") DigitalRadiography, /// (ECG,DCM,"Electrocardiography") Electrocardiography, - /// (EPS,DCM,"Cardiac Electrophysiology") - CardiacElectrophysiology, + /// (EEG,DCM,"Electroencephalography") + Electroencephalography, + /// (EMG,DCM,"Electromyography") + Electromyography, + /// (EOG,DCM,"Electrooculography") + Electrooculography, /// (ES,DCM,"Endoscopy") Endoscopy, + /// (XC,DCM,"External-camera Photography") + ExternalCameraPhotography, /// (GM,DCM,"General Microscopy") GeneralMicroscopy, /// (HD,DCM,"Hemodynamic Waveform") @@ -74,24 +82,22 @@ class DCMTK_CMR_EXPORT CID29_AcquisitionModality IntravascularUltrasound, /// (KER,DCM,"Keratometry") Keratometry, - /// (LEN,DCM,"Lensometry") - Lensometry, /// (LS,DCM,"Laser Scan") LaserScan, - /// (MG,DCM,"Mammography") - Mammography, + /// (LEN,DCM,"Lensometry") + Lensometry, /// (MR,DCM,"Magnetic Resonance") MagneticResonance, + /// (MG,DCM,"Mammography") + Mammography, /// (NM,DCM,"Nuclear Medicine") NuclearMedicine, /// (OAM,DCM,"Ophthalmic Axial Measurements") OphthalmicAxialMeasurements, - /// (OCT,DCM,"Optical Coherence Tomography") - OpticalCoherenceTomography, - /// (OP,DCM,"Ophthalmic Photography") - OphthalmicPhotography, /// (OPM,DCM,"Ophthalmic Mapping") OphthalmicMapping, + /// (OP,DCM,"Ophthalmic Photography") + OphthalmicPhotography, /// (OPT,DCM,"Ophthalmic Tomography") OphthalmicTomography, /// (OPTBSV,DCM,"Ophthalmic Tomography B-scan Volume Analysis") @@ -100,18 +106,22 @@ class DCMTK_CMR_EXPORT CID29_AcquisitionModality OphthalmicTomographyEnFace, /// (OPV,DCM,"Ophthalmic Visual Field") OphthalmicVisualField, + /// (OCT,DCM,"Optical Coherence Tomography") + OpticalCoherenceTomography, /// (OSS,DCM,"Optical Surface Scanner") OpticalSurfaceScanner, - /// (PT,DCM,"Positron emission tomography") - PositronEmissionTomography, /// (PX,DCM,"Panoramic X-Ray") PanoramicXRay, - /// (RESP,DCM,"Respiratory Waveform") - RespiratoryWaveform, + /// (POS,DCM,"Position Sensor") + PositionSensor, + /// (PT,DCM,"Positron emission tomography") + PositronEmissionTomography, /// (RF,DCM,"Radiofluoroscopy") Radiofluoroscopy, /// (RG,DCM,"Radiographic imaging") RadiographicImaging, + /// (RESP,DCM,"Respiratory Waveform") + RespiratoryWaveform, /// (RTIMAGE,DCM,"RT Image") RTImage, /// (SM,DCM,"Slide Microscopy") @@ -122,12 +132,12 @@ class DCMTK_CMR_EXPORT CID29_AcquisitionModality Thermography, /// (US,DCM,"Ultrasound") Ultrasound, + /// (BDUS,DCM,"Ultrasound Bone Densitometry") + UltrasoundBoneDensitometry, /// (VA,DCM,"Visual Acuity") VisualAcuity, /// (XA,DCM,"X-Ray Angiography") - XRayAngiography, - /// (XC,DCM,"External-camera Photography") - ExternalCameraPhotography + XRayAngiography }; /** (default) constructor diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h index 8bc448dd..e9ebfb44 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID4020_PETRadionuclide * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:18 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:55 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h index 3a3a968e..1242c5a8 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID4021_PETRadiopharmaceutical * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:20 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:57 by J. Riesmeier * */ @@ -28,7 +28,7 @@ /** Implementation of DCMR Context Group: * CID 4021 - PET Radiopharmaceutical. - * (type: extensible, version: 20190124) + * (type: extensible, version: 20201116) */ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical : public DSRContextGroup @@ -40,6 +40,8 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical */ enum EnumType { + /// (C000591008,MSH,"^18^Fluorine flortaucipir") + _18_FluorineFlortaucipir, /// (126752,DCM,"28H1 ^89^Zr") _28H1_89Zr, /// (126713,DCM,"2FA F^18^") @@ -112,6 +114,10 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical DfFKPEG3_89Zr, /// (126747,DCM,"DN30 ^89^Zr") DN30_89Zr, + /// (126765,DCM,"DPA-713 ^11^C") + DPA713_11C, + /// (126766,DCM,"DPA-714 ^18^F") + DPA714_18F, /// (126519,DCM,"E4G10 ^89^Zr") E4G10_89Zr, /// (126732,DCM,"Ecromeximab ^89^Zr") @@ -130,7 +136,7 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical Florbetaben_F18, /// (456995000,SCT,"Florbetapir F^18^") Florbetapir_F18, - /// (C4547429,UMLS,"Flortaucipir F^18^") + /// (C000591008,MSH,"Flortaucipir F^18^") Flortaucipir_F18, /// (126503,DCM,"Flubatine F^18^") Flubatine_F18, @@ -154,7 +160,7 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical FluoroestradiolFES_F18, /// (C1541539,UMLS,"Fluoroetanidazole F^18^") Fluoroetanidazole_F18, - /// (129500005,SCT,"Fluoro-L-dopa F^18^") + /// (5811000122108,SCT,"Fluoro-L-dopa F^18^") FluoroLDopa_F18, /// (422763008,SCT,"Fluoromethane F^18^") Fluoromethane_F18, @@ -174,7 +180,7 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical Fresolimumab_89Zr, /// (126731,DCM,"GA201 ^89^Zr") GA201_89Zr, - /// (129516007,SCT,"Germanium Ge^68^") + /// (53315004,SCT,"Germanium Ge^68^") Germanium_Ge68, /// (126724,DCM,"Glembatumumab vedotin ^89^Zr") GlembatumumabVedotin_89Zr, @@ -206,7 +212,7 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical MonoclonalAntibodymAb_64Cu, /// (126511,DCM,"Monoclonal Antibody (mAb) ^89^Zr") MonoclonalAntibodymAb_89Zr, - /// (424874008,SCT,"Monoclonal antibody I^124^") + /// (423249007,SCT,"Monoclonal antibody I^124^") MonoclonalAntibody_I124, /// (126753,DCM,"Nanocolloidal albumin ^89^Zr") NanocolloidalAlbumin_89Zr, @@ -230,6 +236,8 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical PinatuzumabVedotin_89Zr, /// (126500,DCM,"Pittsburgh compound B C^11^") PittsburghCompoundB_C11, + /// (C1609883,UMLS,"PK11195 ^11^C") + PK11195_11C, /// (126726,DCM,"Polatuzumab vedotin ^89^Zr") PolatuzumabVedotin_89Zr, /// (126758,DCM,"PSMA-1007 F^18^") @@ -270,7 +278,7 @@ class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical SodiumFluoride_F18, /// (422980002,SCT,"Sodium iodide I^124^") SodiumIodide_I124, - /// (129517003,SCT,"Sodium Na^22^") + /// (71633006,SCT,"Sodium Na^22^") Sodium_Na22, /// (129499001,SCT,"Spiperone F^18^") Spiperone_F18, diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h index d82bf0ba..28e324ef 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID4031_CommonAnatomicRegions * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:22 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:59 by J. Riesmeier * */ @@ -28,7 +28,7 @@ /** Implementation of DCMR Context Group: * CID 4031 - Common Anatomic Regions. - * (type: extensible, version: 20170914) + * (type: extensible, version: 20200704) */ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions : public DSRContextGroup @@ -40,9 +40,9 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions */ enum EnumType { - /// (113345001,SCT,"Abdomen") + /// (818981001,SCT,"Abdomen") Abdomen, - /// (416949008,SCT,"Abdomen and Pelvis") + /// (818982008,SCT,"Abdomen and Pelvis") AbdomenAndPelvis, /// (85856004,SCT,"Acromioclavicular joint") AcromioclavicularJoint, @@ -70,7 +70,7 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions CervicalSpine, /// (297171002,SCT,"Cervico-thoracic spine") CervicoThoracicSpine, - /// (51185008,SCT,"Chest") + /// (816094009,SCT,"Chest") Chest, /// (416550000,SCT,"Chest and Abdomen") ChestAndAbdomen, @@ -82,6 +82,8 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions Coccyx, /// (71854001,SCT,"Colon") Colon, + /// (79741001,SCT,"Common bile duct") + CommonBileDuct, /// (38848004,SCT,"Duodenum") Duodenum, /// (16953009,SCT,"Elbow joint") @@ -120,7 +122,9 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions HeadAndNeck, /// (80891009,SCT,"Heart") Heart, - /// (29836001,SCT,"Hip joint") + /// (29836001,SCT,"Hip") + Hip, + /// (24136001,SCT,"Hip Joint") HipJoint, /// (85050009,SCT,"Humerus") Humerus, @@ -140,6 +144,8 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions LargeIntestine, /// (4596009,SCT,"Larynx") Larynx, + /// (303270005,SCT,"Liver and biliary structure") + LiverAndBiliaryStructure, /// (30021000,SCT,"Lower leg") LowerLeg, /// (61685007,SCT,"Lower limb") @@ -174,6 +180,10 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions OpticCanal, /// (363654007,SCT,"Orbital structure") OrbitalStructure, + /// (15776009,SCT,"Pancreas") + Pancreas, + /// (69930009,SCT,"Pancreatic duct") + PancreaticDuct, /// (110621006,SCT,"Pancreatic duct and bile duct systems") PancreaticDuctAndBileDuctSystems, /// (2095001,SCT,"Paranasal sinus") @@ -182,7 +192,7 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions ParotidGland, /// (64234005,SCT,"Patella") Patella, - /// (12921003,SCT,"Pelvis") + /// (816092008,SCT,"Pelvis") Pelvis, /// (416631005,SCT,"Pelvis and lower extremities") PelvisAndLowerExtremities, @@ -194,6 +204,8 @@ class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegions Rectum, /// (113197003,SCT,"Rib") Rib, + /// (297174005,SCT,"Sacro-coccygeal Spine") + SacroCoccygealSpine, /// (39723000,SCT,"Sacroiliac joint") SacroiliacJoint, /// (54735007,SCT,"Sacrum") diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid42.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid42.h index feb3501d..6e2df82e 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid42.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid42.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID42_NumericValueQualifier * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:12 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:47 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h index 4c51a00f..7fc03e4e 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID6147_ResponseCriteria * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:24 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:01 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h index 2f2e0053..a99eb4be 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7021_MeasurementReportDocumentTitles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:26 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:03 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h index 4a539f58..048c916e 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7181_AbstractMultiDimensionalImageModelComponentUnits * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:28 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:05 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h index bc33721b..2567e285 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7445_DeviceParticipatingRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:30 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:06 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h index 84603773..b64e0fc2 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7452_OrganizationalRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:32 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:08 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h index 9536a07c..d7160ceb 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7453_PerformingRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:33 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:10 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h index 4edd30a0..14cdd9dd 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7464_GeneralRegionOfInterestMeasurementModifiers * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:35 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:12 by J. Riesmeier * */ diff --git a/dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h b/dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h index 2d38e554..f71d0860 100644 --- a/dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h +++ b/dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file for class CID7469_GenericIntensityAndSizeMeasurements * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:37 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:14 by J. Riesmeier * */ @@ -348,6 +348,12 @@ class DCMTK_CMR_EXPORT CID7469_GenericIntensityAndSizeMeasurements WaterFraction, /// (130086,DCM,"Relative Linear Stopping Power"), included from CID 7180 RelativeLinearStoppingPower, + /// (130402,DCM,"Class activation"), included from CID 217 + ClassActivation, + /// (130403,DCM,"Gradient-weighted class activation"), included from CID 217 + GradientWeightedClassActivation, + /// (130404,DCM,"Saliency"), included from CID 217 + Saliency, /// (410668003,SCT,"Length"), included from CID 7470 Length, /// (121211,DCM,"Path length"), included from CID 7470 @@ -380,6 +386,8 @@ class DCMTK_CMR_EXPORT CID7469_GenericIntensityAndSizeMeasurements DiameterOfCircumscribedCircle, /// (121207,DCM,"Height"), included from CID 7470 Height, + /// (121227,DCM,"Line segment length"), included from CID 7470 + LineSegmentLength, /// (L0JK,IBSI,"Maximum 3D Diameter of a Mesh"), included from CID 7470 Maximum3DDiameterOfAMesh, /// (TDIC,IBSI,"Major Axis in 3D Length"), included from CID 7470 diff --git a/dcmsr/include/dcmtk/dcmsr/codes/dcm.h b/dcmsr/include/dcmtk/dcmsr/codes/dcm.h index 21a284a3..1b3cba54 100644 --- a/dcmsr/include/dcmtk/dcmsr/codes/dcm.h +++ b/dcmsr/include/dcmtk/dcmsr/codes/dcm.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file with DICOM Controlled Terminology Code Definitions (Coding Scheme "DCM", Version "01") * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 16:52:41 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 10:55:18 by J. Riesmeier * */ @@ -34,8 +34,8 @@ * code definitions * *--------------------*/ -// total number of codes: 4218 -// - retired: 194 +// total number of codes: 4387 +// - retired: 199 // - no name: 27 // - not unique: 17 @@ -70,6 +70,7 @@ #define CODE_DCM_RETIRED_DigitalFluoroscopy DSRBasicCodedEntry("DF", "DCM", "Digital fluoroscopy") #define CODE_DCM_Diaphanography DSRBasicCodedEntry("DG", "DCM", "Diaphanography") #define CODE_DCM_RETIRED_DigitalMicroscopy DSRBasicCodedEntry("DM", "DCM", "Digital microscopy") +#define CODE_DCM_Dermoscopy DSRBasicCodedEntry("DMS", "DCM", "Dermoscopy") #define CODE_DCM_Document_DOC DSRBasicCodedEntry("DOC", "DCM", "Document") #define CODE_DCM_DocumentDigitizerEquipment DSRBasicCodedEntry("DOCD", "DCM", "Document Digitizer Equipment") #define CODE_DCM_RETIRED_DigitalSubtractionAngiography DSRBasicCodedEntry("DS", "DCM", "Digital Subtraction Angiography") @@ -77,6 +78,9 @@ #define CODE_DCM_DigitalRadiography DSRBasicCodedEntry("DX", "DCM", "Digital Radiography") #define CODE_DCM_RETIRED_Echocardiography DSRBasicCodedEntry("EC", "DCM", "Echocardiography") #define CODE_DCM_Electrocardiography DSRBasicCodedEntry("ECG", "DCM", "Electrocardiography") +#define CODE_DCM_Electroencephalography DSRBasicCodedEntry("EEG", "DCM", "Electroencephalography") +#define CODE_DCM_Electromyography DSRBasicCodedEntry("EMG", "DCM", "Electromyography") +#define CODE_DCM_Electrooculography DSRBasicCodedEntry("EOG", "DCM", "Electrooculography") #define CODE_DCM_CardiacElectrophysiology DSRBasicCodedEntry("EPS", "DCM", "Cardiac Electrophysiology") #define CODE_DCM_Endoscopy DSRBasicCodedEntry("ES", "DCM", "Endoscopy") #define CODE_DCM_Female DSRBasicCodedEntry("F", "DCM", "Female") @@ -126,6 +130,7 @@ #define CODE_DCM_OpticalSurfaceScanner DSRBasicCodedEntry("OSS", "DCM", "Optical Surface Scanner") #define CODE_DCM_OtherModality DSRBasicCodedEntry("OT", "DCM", "Other Modality") #define CODE_DCM_Plan DSRBasicCodedEntry("PLAN", "DCM", "Plan") +#define CODE_DCM_PositionSensor DSRBasicCodedEntry("POS", "DCM", "Position Sensor") #define CODE_DCM_PresentationState DSRBasicCodedEntry("PR", "DCM", "Presentation State") #define CODE_DCM_HardCopyPrintServer DSRBasicCodedEntry("PRINT", "DCM", "Hard Copy Print Server") #define CODE_DCM_PositronEmissionTomography DSRBasicCodedEntry("PT", "DCM", "Positron emission tomography") @@ -148,6 +153,7 @@ #define CODE_DCM_SubjectiveRefraction DSRBasicCodedEntry("SRF", "DCM", "Subjective Refraction") #define CODE_DCM_RETIRED_SinglePhotonEmissionComputedTomography DSRBasicCodedEntry("ST", "DCM", "Single-photon emission computed tomography") #define CODE_DCM_AutomatedSlideStainer DSRBasicCodedEntry("STAIN", "DCM", "Automated Slide Stainer") +#define CODE_DCM_TextureMap DSRBasicCodedEntry("TEXTUREMAP", "DCM", "Texture Map") #define CODE_DCM_Thermography DSRBasicCodedEntry("TG", "DCM", "Thermography") #define CODE_DCM_UnknownSex DSRBasicCodedEntry("U", "DCM", "Unknown Sex") #define CODE_DCM_Unavailable DSRBasicCodedEntry("UNAVAILABLE", "DCM", "Unavailable") @@ -621,6 +627,7 @@ #define CODE_DCM_ImageOrientation_Patient_ColumnZ DSRBasicCodedEntry("110909", "DCM", "Image Orientation (Patient) Column Z") #define CODE_DCM_PixelDataRows DSRBasicCodedEntry("110910", "DCM", "Pixel Data Rows") #define CODE_DCM_PixelDataColumns DSRBasicCodedEntry("110911", "DCM", "Pixel Data Columns") +#define CODE_DCM_AlgorithmFamily DSRBasicCodedEntry("111000", "DCM", "Algorithm Family") #define CODE_DCM_AlgorithmName DSRBasicCodedEntry("111001", "DCM", "Algorithm Name") #define CODE_DCM_AlgorithmParameters DSRBasicCodedEntry("111002", "DCM", "Algorithm Parameters") #define CODE_DCM_AlgorithmVersion DSRBasicCodedEntry("111003", "DCM", "Algorithm Version") @@ -948,7 +955,7 @@ #define CODE_DCM_GreaterThan1YearAgo DSRBasicCodedEntry("111398", "DCM", "> 1 year ago") #define CODE_DCM_TimeframeUncertain DSRBasicCodedEntry("111399", "DCM", "Timeframe uncertain") #define CODE_DCM_BreastImagingReport DSRBasicCodedEntry("111400", "DCM", "Breast Imaging Report") -#define CODE_DCM_ReasonForProcedure DSRBasicCodedEntry("111401", "DCM", "Reason for procedure") +#define CODE_DCM_RETIRED_ReasonForProcedure DSRBasicCodedEntry("111401", "DCM", "Reason for Procedure") #define CODE_DCM_ClinicalFinding DSRBasicCodedEntry("111402", "DCM", "Clinical Finding") #define CODE_DCM_BaselineScreeningMammogram DSRBasicCodedEntry("111403", "DCM", "Baseline screening mammogram") #define CODE_DCM_FirstMammogramEver DSRBasicCodedEntry("111404", "DCM", "First mammogram ever") @@ -956,7 +963,7 @@ #define CODE_DCM_NumberOfSimilarFindings DSRBasicCodedEntry("111406", "DCM", "Number of similar findings") #define CODE_DCM_ImplantFinding DSRBasicCodedEntry("111407", "DCM", "Implant finding") #define CODE_DCM_FilmScreenMammography DSRBasicCodedEntry("111408", "DCM", "Film Screen Mammography") -#define CODE_DCM_DigitalMammography DSRBasicCodedEntry("111409", "DCM", "Digital Mammography") +#define CODE_DCM_RETIRED_DigitalMammography DSRBasicCodedEntry("111409", "DCM", "Digital Mammography") #define CODE_DCM_SurgicalConsult DSRBasicCodedEntry("111410", "DCM", "Surgical consult") #define CODE_DCM_MammographyCAD DSRBasicCodedEntry("111411", "DCM", "Mammography CAD") #define CODE_DCM_NarrativeSummary DSRBasicCodedEntry("111412", "DCM", "Narrative Summary") @@ -1521,7 +1528,7 @@ #define CODE_DCM_PoorlyDemarcated DSRBasicCodedEntry("112141", "DCM", "Poorly demarcated") #define CODE_DCM_RETIRED_Circumscribed DSRBasicCodedEntry("112142", "DCM", "Circumscribed") #define CODE_DCM_Air DSRBasicCodedEntry("112143", "DCM", "Air") -#define CODE_DCM_SoftTissue DSRBasicCodedEntry("112144", "DCM", "Soft tissue") +#define CODE_DCM_RETIRED_SoftTissue DSRBasicCodedEntry("112144", "DCM", "Soft tissue") #define CODE_DCM_Calcium DSRBasicCodedEntry("112145", "DCM", "Calcium") #define CODE_DCM_Acinar DSRBasicCodedEntry("112146", "DCM", "Acinar") #define CODE_DCM_AirSpace DSRBasicCodedEntry("112147", "DCM", "Air space") @@ -2102,10 +2109,11 @@ #define CODE_DCM_CTDIvolNotificationValue DSRBasicCodedEntry("113912", "DCM", "CTDIvol Notification Value") #define CODE_DCM_DLPForwardEstimate DSRBasicCodedEntry("113913", "DCM", "DLP Forward Estimate") #define CODE_DCM_CTDIvolForwardEstimate DSRBasicCodedEntry("113914", "DCM", "CTDIvol Forward Estimate") +#define CODE_DCM_AlternativeDoseAlertBehaviorActive DSRBasicCodedEntry("113915", "DCM", "Alternative dose alert behavior active") #define CODE_DCM_RadiationExposure DSRBasicCodedEntry("113921", "DCM", "Radiation Exposure") #define CODE_DCM_RETIRED_RadioactiveSubstanceAdministered DSRBasicCodedEntry("113922", "DCM", "Radioactive Substance Administered") #define CODE_DCM_RETIRED_RadiationExposureAndProtectionInformation DSRBasicCodedEntry("113923", "DCM", "Radiation Exposure and Protection Information") -#define CODE_DCM_SizeSpecificDoseEstimation DSRBasicCodedEntry("113930", "DCM", "Size Specific Dose Estimation") +#define CODE_DCM_SizeSpecificDoseEstimate DSRBasicCodedEntry("113930", "DCM", "Size Specific Dose Estimate") #define CODE_DCM_MeasuredLateralDimension DSRBasicCodedEntry("113931", "DCM", "Measured Lateral Dimension") #define CODE_DCM_MeasuredAPDimension DSRBasicCodedEntry("113932", "DCM", "Measured AP Dimension") #define CODE_DCM_DerivedEffectiveDiameter DSRBasicCodedEntry("113933", "DCM", "Derived Effective Diameter") @@ -2146,6 +2154,14 @@ #define CODE_DCM_SeriesOrInstanceUsedForWaterEquivalentDiameterEstimation DSRBasicCodedEntry("113985", "DCM", "Series or Instance used for Water Equivalent Diameter estimation") #define CODE_DCM_ZValueOfLocationOfWaterEquivalentDiameterEstimation DSRBasicCodedEntry("113986", "DCM", "Z value of location of Water Equivalent Diameter estimation") #define CODE_DCM_AAPM220 DSRBasicCodedEntry("113987", "DCM", "AAPM 220") +#define CODE_DCM_EstimatedFromWaterEquivalentDiameter DSRBasicCodedEntry("113988", "DCM", "Estimated from Water Equivalent Diameter") +#define CODE_DCM_ArithmeticAverageOfSSDEz DSRBasicCodedEntry("113989", "DCM", "Arithmetic Average of SSDE(z)") +#define CODE_DCM_ArithmeticAverageOfDwz DSRBasicCodedEntry("113990", "DCM", "Arithmetic Average of Dw(z)") +#define CODE_DCM_DwConversionFactorCoefficients DSRBasicCodedEntry("113991", "DCM", "Dw Conversion Factor Coefficients") +#define CODE_DCM_WaterEquivalentDiameterFromLimitedFOVImages DSRBasicCodedEntry("113992", "DCM", "Water Equivalent Diameter From Limited FOV Images") +#define CODE_DCM_SizeSpecificDoseEstimateAtLongitudinalPositionZ DSRBasicCodedEntry("113993", "DCM", "Size Specific Dose Estimate At Longitudinal Position Z") +#define CODE_DCM_LongitudinalPositionZ DSRBasicCodedEntry("113994", "DCM", "Longitudinal Position Z") +#define CODE_DCM_WaterEquivalentDiameterAtLongitudinalPositionZ DSRBasicCodedEntry("113995", "DCM", "Water Equivalent Diameter At Longitudinal Position Z") #define CODE_DCM_NotANumber DSRBasicCodedEntry("114000", "DCM", "Not a number") #define CODE_DCM_NegativeInfinity DSRBasicCodedEntry("114001", "DCM", "Negative Infinity") #define CODE_DCM_PositiveInfinity DSRBasicCodedEntry("114002", "DCM", "Positive Infinity") @@ -2172,6 +2188,8 @@ #define CODE_DCM_IterativeClosestPoint DSRBasicCodedEntry("114213", "DCM", "Iterative Closest Point") #define CODE_DCM_Freehand DSRBasicCodedEntry("114215", "DCM", "Freehand") #define CODE_DCM_Checkerboard DSRBasicCodedEntry("114216", "DCM", "Checkerboard") +#define CODE_DCM_DeviceDescription DSRBasicCodedEntry("120999", "DCM", "Device Description") +#define CODE_DCM_UniqueDeviceIdentifiers DSRBasicCodedEntry("121000", "DCM", "Unique Device Identifiers") #define CODE_DCM_QuotationMode DSRBasicCodedEntry("121001", "DCM", "Quotation Mode") #define CODE_DCM_QuotedSource DSRBasicCodedEntry("121002", "DCM", "Quoted Source") #define CODE_DCM_Document_121003 DSRBasicCodedEntry("121003", "DCM", "Document") @@ -2232,6 +2250,7 @@ #define CODE_DCM_ProcedureReported DSRBasicCodedEntry("121058", "DCM", "Procedure reported") #define CODE_DCM_RETIRED_PresenceUndetermined DSRBasicCodedEntry("121059", "DCM", "Presence Undetermined") #define CODE_DCM_RETIRED_History DSRBasicCodedEntry("121060", "DCM", "History") +#define CODE_DCM_DeviceObserverManufacturerClassUID DSRBasicCodedEntry("121061", "DCM", "Device Observer Manufacturer Class UID") #define CODE_DCM_RETIRED_Request DSRBasicCodedEntry("121062", "DCM", "Request") #define CODE_DCM_RETIRED_CurrentProcedureDescriptions DSRBasicCodedEntry("121064", "DCM", "Current Procedure Descriptions") #define CODE_DCM_ProcedureDescription DSRBasicCodedEntry("121065", "DCM", "Procedure Description") @@ -2363,6 +2382,11 @@ #define CODE_DCM_VolumeOfCircumscribedSphere DSRBasicCodedEntry("121220", "DCM", "Volume of circumscribed sphere") #define CODE_DCM_VolumeOfEllipsoid DSRBasicCodedEntry("121221", "DCM", "Volume of ellipsoid") #define CODE_DCM_VolumeOfSphere DSRBasicCodedEntry("121222", "DCM", "Volume of sphere") +#define CODE_DCM_ArmOfAngle DSRBasicCodedEntry("121223", "DCM", "Arm of angle") +#define CODE_DCM_AcetabularAngle DSRBasicCodedEntry("121224", "DCM", "Acetabular angle") +#define CODE_DCM_Vector DSRBasicCodedEntry("121225", "DCM", "Vector") +#define CODE_DCM_ApproximateSpatialLocation DSRBasicCodedEntry("121226", "DCM", "Approximate spatial location") +#define CODE_DCM_LineSegmentLength DSRBasicCodedEntry("121227", "DCM", "Line segment length") #define CODE_DCM_PathVertex DSRBasicCodedEntry("121230", "DCM", "Path Vertex") #define CODE_DCM_VolumeSurface DSRBasicCodedEntry("121231", "DCM", "Volume Surface") #define CODE_DCM_SourceSeriesForSegmentation DSRBasicCodedEntry("121232", "DCM", "Source series for segmentation") @@ -2434,6 +2458,12 @@ #define CODE_DCM_ContrastBolusIngredientOpaque DSRBasicCodedEntry("121381", "DCM", "Contrast/Bolus Ingredient Opaque") #define CODE_DCM_QuantityAdministered DSRBasicCodedEntry("121382", "DCM", "Quantity administered") #define CODE_DCM_MassAdministered DSRBasicCodedEntry("121383", "DCM", "Mass administered") +#define CODE_DCM_RTPlanLabel DSRBasicCodedEntry("121384", "DCM", "RT Plan Label") +#define CODE_DCM_CurrentFractionNumber DSRBasicCodedEntry("121385", "DCM", "Current Fraction Number") +#define CODE_DCM_NumberOfFractionsPlanned DSRBasicCodedEntry("121386", "DCM", "Number of Fractions Planned") +#define CODE_DCM_NumberOfFractionsCompleted DSRBasicCodedEntry("121387", "DCM", "Number of Fractions Completed") +#define CODE_DCM_CheckedInStatus DSRBasicCodedEntry("121388", "DCM", "Checked-In Status") +#define CODE_DCM_ReferencedBeamNumber DSRBasicCodedEntry("121389", "DCM", "Referenced Beam Number") #define CODE_DCM_Derivation DSRBasicCodedEntry("121401", "DCM", "Derivation") #define CODE_DCM_Normality DSRBasicCodedEntry("121402", "DCM", "Normality") #define CODE_DCM_LevelOfSignificance DSRBasicCodedEntry("121403", "DCM", "Level of Significance") @@ -2703,13 +2733,13 @@ #define CODE_DCM_CorrectedSinusNodeRecoveryTime DSRBasicCodedEntry("122237", "DCM", "Corrected Sinus Node Recovery Time") #define CODE_DCM_MaxVolumeNormalizedTo50mmHgPulsePressure DSRBasicCodedEntry("122238", "DCM", "Max volume normalized to 50mmHg pulse pressure") #define CODE_DCM_OxygenConsumption DSRBasicCodedEntry("122239", "DCM", "Oxygen Consumption") -#define CODE_DCM_122240 DSRBasicCodedEntry("122240", "DCM", "BSA = 3.207*WT^(0.7285-0.0188 log (WT)) *HT^0.3") -#define CODE_DCM_122241 DSRBasicCodedEntry("122241", "DCM", "BSA = 0.007184*WT^ 0.425*HT^0.725") -#define CODE_DCM_122242 DSRBasicCodedEntry("122242", "DCM", "BSA = 0.0235*WT^0.51456*HT^ 0.42246") +#define CODE_DCM_122240 DSRBasicCodedEntry("122240", "DCM", "BSA = 0.003207*WT^(0.7285-0.0188*log(WT))*HT^0.3") +#define CODE_DCM_122241 DSRBasicCodedEntry("122241", "DCM", "BSA = 0.007184*WT^0.425*HT^0.725") +#define CODE_DCM_122242 DSRBasicCodedEntry("122242", "DCM", "BSA = 0.0235*WT^0.51456*HT^0.42246") #define CODE_DCM_122243 DSRBasicCodedEntry("122243", "DCM", "BSA = 0.024265*WT^0.5378*HT^0.3964") -#define CODE_DCM_122244 DSRBasicCodedEntry("122244", "DCM", "BSA = (HT * WT/36) ^0.5") +#define CODE_DCM_122244 DSRBasicCodedEntry("122244", "DCM", "BSA = (HT*WT/36)^0.5") #define CODE_DCM_122245 DSRBasicCodedEntry("122245", "DCM", "BSA = 1321+0.3433*WT") -#define CODE_DCM_122246 DSRBasicCodedEntry("122246", "DCM", "BSA = 0.0004688 * WT ^ (0.8168 - 0.0154 * log(WT))") +#define CODE_DCM_122246 DSRBasicCodedEntry("122246", "DCM", "BSA = 0.0004688*WT^(0.8168-0.0154*log(WT))") #define CODE_DCM_122247 DSRBasicCodedEntry("122247", "DCM", "VO2male = BSA (138.1 - 11.49 * loge(age) + 0.378 * HRf)") #define CODE_DCM_122248 DSRBasicCodedEntry("122248", "DCM", "VO2female = BSA (138.1 - 17.04 * loge(age) + 0.378 * HRf)") #define CODE_DCM_122249 DSRBasicCodedEntry("122249", "DCM", "VO2 = VeSTPD * 10 * (FIO2 - FE02)") @@ -2728,11 +2758,11 @@ #define CODE_DCM_122262 DSRBasicCodedEntry("122262", "DCM", "Area = Flow / 44.5 * sqrt(Gradient[mmHg])") #define CODE_DCM_122263 DSRBasicCodedEntry("122263", "DCM", "MVA = Flow / 38.0 * sqrt(Gradient[mmHg])") #define CODE_DCM_122265 DSRBasicCodedEntry("122265", "DCM", "BMI = Wt / Ht ^ 2") -#define CODE_DCM_122266 DSRBasicCodedEntry("122266", "DCM", "BSA = 0.007358 * WT ^ 0.425 * HT ^ 0.725") -#define CODE_DCM_122267 DSRBasicCodedEntry("122267", "DCM", "BSA = 0.010265 * WT ^ 0.423 * HT ^ 0.651") -#define CODE_DCM_122268 DSRBasicCodedEntry("122268", "DCM", "BSA = 0.008883 * WT ^ 0.444 * HT ^ 0.663") -#define CODE_DCM_122269 DSRBasicCodedEntry("122269", "DCM", "BSA = 0.038189 * WT ^ 0.423 * HT ^ 0.362") -#define CODE_DCM_122270 DSRBasicCodedEntry("122270", "DCM", "BSA = 0.009568 * WT ^ 0.473 * HT ^ 0.655") +#define CODE_DCM_122266 DSRBasicCodedEntry("122266", "DCM", "BSA = 0.007358*WT^0.425*HT^0.725") +#define CODE_DCM_122267 DSRBasicCodedEntry("122267", "DCM", "BSA = 0.010265*WT^0.423*HT^0.651") +#define CODE_DCM_122268 DSRBasicCodedEntry("122268", "DCM", "BSA = 0.008883*WT^0.444*HT^0.663") +#define CODE_DCM_122269 DSRBasicCodedEntry("122269", "DCM", "BSA = 0.038189*WT^0.423*HT^0.362") +#define CODE_DCM_122270 DSRBasicCodedEntry("122270", "DCM", "BSA = 0.009568*WT^0.473*HT^0.655") #define CODE_DCM_SkinConditionWarm DSRBasicCodedEntry("122271", "DCM", "Skin Condition Warm") #define CODE_DCM_SkinConditionCool DSRBasicCodedEntry("122272", "DCM", "Skin Condition Cool") #define CODE_DCM_SkinConditionCold DSRBasicCodedEntry("122273", "DCM", "Skin Condition Cold") @@ -2888,7 +2918,7 @@ #define CODE_DCM_FrameToFrameAnalysis DSRBasicCodedEntry("122499", "DCM", "Frame to Frame Analysis") #define CODE_DCM_AreaOfClosedIrregularPolygon DSRBasicCodedEntry("122501", "DCM", "Area of closed irregular polygon") #define CODE_DCM_AreaOfAClosedNURBS DSRBasicCodedEntry("122502", "DCM", "Area of a closed NURBS") -#define CODE_DCM_IntegrationOfSumOfClosedAreasonContiguousSlices DSRBasicCodedEntry("122503", "DCM", "Integration of sum of closed areas on contiguous slices") +#define CODE_DCM_IntegrationOfSumOfClosedAreasonContiguousSlicesMethodForVolume DSRBasicCodedEntry("122503", "DCM", "Integration of sum of closed areas on contiguous slices method for volume") #define CODE_DCM_Calibration DSRBasicCodedEntry("122505", "DCM", "Calibration") #define CODE_DCM_LeftContour DSRBasicCodedEntry("122507", "DCM", "Left Contour") #define CODE_DCM_RightContour DSRBasicCodedEntry("122508", "DCM", "Right Contour") @@ -3096,6 +3126,9 @@ #define CODE_DCM_AcquisitionEquipmentAlignment DSRBasicCodedEntry("125023", "DCM", "Acquisition Equipment Alignment") #define CODE_DCM_ImageContentBasedAlignment DSRBasicCodedEntry("125024", "DCM", "Image Content-based Alignment") #define CODE_DCM_VisualAlignment DSRBasicCodedEntry("125025", "DCM", "Visual Alignment") +#define CODE_DCM_ImageContentAndFiducialBasedAlignment DSRBasicCodedEntry("125026", "DCM", "Image Content and Fiducial Based Alignment") +#define CODE_DCM_DeformedForRegistration DSRBasicCodedEntry("125027", "DCM", "Deformed for Registration") +#define CODE_DCM_SourceDeformableSpatialRegistration DSRBasicCodedEntry("125028", "DCM", "Source Deformable Spatial Registration") #define CODE_DCM_InterHemisphericPlane DSRBasicCodedEntry("125030", "DCM", "Inter-Hemispheric Plane") #define CODE_DCM_RightHemisphereMostAnterior DSRBasicCodedEntry("125031", "DCM", "Right Hemisphere Most Anterior") #define CODE_DCM_RightHemisphereMostPosterior DSRBasicCodedEntry("125032", "DCM", "Right Hemisphere Most Posterior") @@ -3107,7 +3140,7 @@ #define CODE_DCM_LeftHemisphereMostInferior DSRBasicCodedEntry("125038", "DCM", "Left Hemisphere Most Inferior") #define CODE_DCM_Background DSRBasicCodedEntry("125040", "DCM", "Background") #define CODE_DCM_RegistrationInput DSRBasicCodedEntry("125041", "DCM", "Registration Input") -#define CODE_DCM_VascularUltrasoundProcedureReport DSRBasicCodedEntry("125100", "DCM", "Vascular Ultrasound Procedure Report") +#define CODE_DCM_RETIRED_VascularUltrasoundProcedureReport DSRBasicCodedEntry("125100", "DCM", "Vascular Ultrasound Procedure Report") #define CODE_DCM_VesselBranch DSRBasicCodedEntry("125101", "DCM", "Vessel Branch") #define CODE_DCM_GraftType DSRBasicCodedEntry("125102", "DCM", "Graft Type") #define CODE_DCM_MeasurementOrientation DSRBasicCodedEntry("125105", "DCM", "Measurement Orientation") @@ -3226,7 +3259,8 @@ #define CODE_DCM_MultiparametricMRI DSRBasicCodedEntry("126020", "DCM", "Multiparametric MRI") #define CODE_DCM_MultiparametricMRIOfProstate DSRBasicCodedEntry("126021", "DCM", "Multiparametric MRI of prostate") #define CODE_DCM_MultiparametricMRIOfWholeBody DSRBasicCodedEntry("126022", "DCM", "Multiparametric MRI of whole body") -#define CODE_DCM_SumOfSegmentedVoxelVolumes DSRBasicCodedEntry("126030", "DCM", "Sum of segmented voxel volumes") +#define CODE_DCM_LWHMethodForVolumeOfEllipsoid DSRBasicCodedEntry("126029", "DCM", "LWH method for volume of ellipsoid") +#define CODE_DCM_SumOfSegmentedVoxelMethodForVolume DSRBasicCodedEntry("126030", "DCM", "Sum of segmented voxel method for volume") #define CODE_DCM_PeakValueWithinROI DSRBasicCodedEntry("126031", "DCM", "Peak Value Within ROI") #define CODE_DCM_MetabolicVolume DSRBasicCodedEntry("126032", "DCM", "Metabolic Volume") #define CODE_DCM_TotalLesionGlycolysis DSRBasicCodedEntry("126033", "DCM", "Total Lesion Glycolysis") @@ -3337,6 +3371,7 @@ #define CODE_DCM_Florbetaben_F18 DSRBasicCodedEntry("126501", "DCM", "Florbetaben F^18^") #define CODE_DCM_T807_F18 DSRBasicCodedEntry("126502", "DCM", "T807 F^18^") #define CODE_DCM_Flubatine_F18 DSRBasicCodedEntry("126503", "DCM", "Flubatine F^18^") +#define CODE_DCM_Lutetium177NAcetylaspartylglutamate DSRBasicCodedEntry("126509", "DCM", "Lutetium^177^ n-acetylaspartylglutamate") #define CODE_DCM_MonoclonalAntibody_mAb_64Cu DSRBasicCodedEntry("126510", "DCM", "Monoclonal Antibody (mAb) ^64^Cu") #define CODE_DCM_MonoclonalAntibody_mAb_89Zr DSRBasicCodedEntry("126511", "DCM", "Monoclonal Antibody (mAb) ^89^Zr") #define CODE_DCM_Trastuzumab_89Zr DSRBasicCodedEntry("126512", "DCM", "Trastuzumab ^89^Zr") @@ -3417,7 +3452,10 @@ #define CODE_DCM_DfFKPEG3_89Zr DSRBasicCodedEntry("126761", "DCM", "Df-FK-PEG(3) ^89^Zr") #define CODE_DCM_DfFK2_89Zr DSRBasicCodedEntry("126762", "DCM", "Df-[FK](2) ^89^Zr") #define CODE_DCM_DfFK23PEG4_89Zr DSRBasicCodedEntry("126763", "DCM", "Df-[FK](2)-3PEG(4) ^89^Zr") -#define CODE_DCM_IEC61217PatientSupportContinuousAngle DSRBasicCodedEntry("126801", "DCM", "IEC61217 Patient Support Continuous Angle") +#define CODE_DCM_Iodinated_I125DPA713 DSRBasicCodedEntry("126764", "DCM", "Iodinated I^125^ DPA-713") +#define CODE_DCM_DPA713_11C DSRBasicCodedEntry("126765", "DCM", "DPA-713 ^11^C") +#define CODE_DCM_DPA714_18F DSRBasicCodedEntry("126766", "DCM", "DPA-714 ^18^F") +#define CODE_DCM_IEC61217PatientSupportContinuousYawAngle DSRBasicCodedEntry("126801", "DCM", "IEC61217 Patient Support Continuous Yaw Angle") #define CODE_DCM_IEC61217TableTopContinuousPitchAngle DSRBasicCodedEntry("126802", "DCM", "IEC61217 Table Top Continuous Pitch Angle") #define CODE_DCM_IEC61217TableTopContinuousRollAngle DSRBasicCodedEntry("126803", "DCM", "IEC61217 Table Top Continuous Roll Angle") #define CODE_DCM_IEC61217TableTopEccentricAxisDistance DSRBasicCodedEntry("126804", "DCM", "IEC61217 Table Top Eccentric Axis Distance") @@ -3550,7 +3588,7 @@ #define CODE_DCM_MouseAlphaSynucleinPreformedFibrils DSRBasicCodedEntry("127852", "DCM", "Mouse alpha synuclein preformed fibrils") #define CODE_DCM_HumanTauPreformedFibrils DSRBasicCodedEntry("127853", "DCM", "Human Tau preformed fibrils") #define CODE_DCM_MouseTauPreformedFibrils DSRBasicCodedEntry("127854", "DCM", "Mouse Tau preformed fibrils") -#define CODE_DCM_NonIonicIodinatedContrastAgent DSRBasicCodedEntry("127855", "DCM", "Non-ionic iodinated contrast agent") +#define CODE_DCM_RETIRED_NonIonicIodinatedContrastAgent DSRBasicCodedEntry("127855", "DCM", "Non-ionic iodinated contrast agent") #define CODE_DCM_HeartValveFlail DSRBasicCodedEntry("127856", "DCM", "Heart valve flail") #define CODE_DCM_GlucoseMeasurementDate DSRBasicCodedEntry("127857", "DCM", "Glucose Measurement Date") #define CODE_DCM_GlucoseMeasurementTime DSRBasicCodedEntry("127858", "DCM", "Glucose Measurement Time") @@ -4202,7 +4240,7 @@ #define CODE_DCM_AdverseEventDetectionDateTime DSRBasicCodedEntry("130215", "DCM", "Adverse Event Detection DateTime") #define CODE_DCM_ReferencedImagingAgentAdministrationStepUID DSRBasicCodedEntry("130216", "DCM", "Referenced Imaging Agent Administration Step UID") #define CODE_DCM_ReferencedImagingAgentAdministrationPhaseIdentifier DSRBasicCodedEntry("130217", "DCM", "Referenced Imaging Agent Administration Phase Identifier") -#define CODE_DCM_ProgrammableDevice DSRBasicCodedEntry("130218", "DCM", "Programmable Device") +#define CODE_DCM_ProgrammableInjectorDevice DSRBasicCodedEntry("130218", "DCM", "Programmable Injector Device") #define CODE_DCM_NumberOfInjectorHeads DSRBasicCodedEntry("130219", "DCM", "Number of Injector Heads") #define CODE_DCM_AdministrationDiscontinued DSRBasicCodedEntry("130220", "DCM", "Administration discontinued") #define CODE_DCM_ImagingAgentVolumePerUnitOfPresentation DSRBasicCodedEntry("130221", "DCM", "Imaging Agent Volume per Unit of Presentation") @@ -4220,7 +4258,7 @@ #define CODE_DCM_ImagingAgentAdministrationInjectorEventType DSRBasicCodedEntry("130234", "DCM", "Imaging Agent Administration Injector Event Type") #define CODE_DCM_InjectorEventDetectionDateTime DSRBasicCodedEntry("130235", "DCM", "Injector Event Detection DateTime") #define CODE_DCM_PlannedImagingAgentAdministrationSOPInstance DSRBasicCodedEntry("130236", "DCM", "Planned Imaging Agent Administration SOP Instance") -#define CODE_DCM_ImagingAgentAdministrationSyringePumpPhaseActivity DSRBasicCodedEntry("130237", "DCM", "Imaging Agent Administration Syringe/Pump Phase Activity") +#define CODE_DCM_ImagingAgentAdministrationActivity DSRBasicCodedEntry("130237", "DCM", "Imaging Agent Administration Activity") #define CODE_DCM_ImagingAgentComponent DSRBasicCodedEntry("130238", "DCM", "Imaging Agent Component") #define CODE_DCM_ComponentVolume DSRBasicCodedEntry("130239", "DCM", "Component Volume") #define CODE_DCM_TotalPhaseVolumeAdministered DSRBasicCodedEntry("130240", "DCM", "Total Phase Volume Administered") @@ -4242,6 +4280,7 @@ #define CODE_DCM_ContrastReactionProphylacticAgent DSRBasicCodedEntry("130259", "DCM", "Contrast Reaction Prophylactic Agent") #define CODE_DCM_ImagingAgentAdministrationPerformedPhaseUID DSRBasicCodedEntry("130261", "DCM", "Imaging Agent Administration Performed Phase UID") #define CODE_DCM_ReferencedImagingAgentAdministrationPhaseUID DSRBasicCodedEntry("130262", "DCM", "Referenced Imaging Agent Administration Phase UID") +#define CODE_DCM_Median DSRBasicCodedEntry("130290", "DCM", "Median") #define CODE_DCM_SkinOfParaspinalAreaOfTheNeck DSRBasicCodedEntry("130300", "DCM", "Skin of paraspinal area of the neck") #define CODE_DCM_SkinOfParaspinalAreaOfTheSuperiorBack DSRBasicCodedEntry("130301", "DCM", "Skin of paraspinal area of the superior back") #define CODE_DCM_SkinOfUpperParaspinalRegion DSRBasicCodedEntry("130302", "DCM", "Skin of upper paraspinal region") @@ -4266,5 +4305,135 @@ #define CODE_DCM_SkinOfUpperAntihelixOfEar DSRBasicCodedEntry("130321", "DCM", "Skin of upper antihelix of ear") #define CODE_DCM_SkinOfUpperEyelidMargin DSRBasicCodedEntry("130322", "DCM", "Skin of upper eyelid margin") #define CODE_DCM_SkinOfMidBack DSRBasicCodedEntry("130323", "DCM", "Skin of mid back") +#define CODE_DCM_FunctionalConditionPresentDuringAcquisition DSRBasicCodedEntry("130324", "DCM", "Functional condition present during acquisition") +#define CODE_DCM_JawPair DSRBasicCodedEntry("130330", "DCM", "Jaw Pair") +#define CODE_DCM_LeafPairs DSRBasicCodedEntry("130331", "DCM", "Leaf Pairs") +#define CODE_DCM_VariableCircularCollimator DSRBasicCodedEntry("130332", "DCM", "Variable Circular Collimator") +#define CODE_DCM_SingleLeaves DSRBasicCodedEntry("130333", "DCM", "Single Leaves") +#define CODE_DCM_XOrientation DSRBasicCodedEntry("130334", "DCM", "X Orientation") +#define CODE_DCM_YOrientation DSRBasicCodedEntry("130335", "DCM", "Y Orientation") +#define CODE_DCM_PhysicalCompensator DSRBasicCodedEntry("130340", "DCM", "Physical Compensator") +#define CODE_DCM_TotalBodyIrradiation DSRBasicCodedEntry("130341", "DCM", "Total Body Irradiation") +#define CODE_DCM_TotalSkinIrradiation DSRBasicCodedEntry("130342", "DCM", "Total Skin Irradiation") +#define CODE_DCM_IsocentricPatientSupportContinuousPitchAngle DSRBasicCodedEntry("126812", "DCM", "Isocentric Patient Support Continuous Pitch Angle") +#define CODE_DCM_IsocentricPatientSupportContinuousRollAngle DSRBasicCodedEntry("126813", "DCM", "Isocentric Patient Support Continuous Roll Angle") +#define CODE_DCM_IsocentricPatientSupportContinuousYawAngle DSRBasicCodedEntry("126814", "DCM", "Isocentric Patient Support Continuous Yaw Angle") +#define CODE_DCM_IsocentricPatientSupportLateralPosition DSRBasicCodedEntry("126815", "DCM", "Isocentric Patient Support Lateral Position") +#define CODE_DCM_IsocentricPatientSupportLongitudinalPosition DSRBasicCodedEntry("126816", "DCM", "Isocentric Patient Support Longitudinal Position") +#define CODE_DCM_IsocentricPatientSupportVerticalPosition DSRBasicCodedEntry("126817", "DCM", "Isocentric Patient Support Vertical Position") +#define CODE_DCM_ElectronFixedAperture DSRBasicCodedEntry("130343", "DCM", "Electron Fixed Aperture") +#define CODE_DCM_PhotonFixedAperture DSRBasicCodedEntry("130344", "DCM", "Photon Fixed Aperture") +#define CODE_DCM_IntraoperativeFixedAperture DSRBasicCodedEntry("130345", "DCM", "Intraoperative Fixed Aperture") +#define CODE_DCM_HardWedge DSRBasicCodedEntry("130346", "DCM", "Hard Wedge") +#define CODE_DCM_MotorizedWedge DSRBasicCodedEntry("130347", "DCM", "Motorized Wedge") +#define CODE_DCM_DynamicWedge DSRBasicCodedEntry("130348", "DCM", "Dynamic Wedge") +#define CODE_DCM_Graticule DSRBasicCodedEntry("130349", "DCM", "Graticule") +#define CODE_DCM_Reticle DSRBasicCodedEntry("130350", "DCM", "Reticle") +#define CODE_DCM_ImageDetector DSRBasicCodedEntry("130351", "DCM", "Image Detector") +#define CODE_DCM_FilmHolder DSRBasicCodedEntry("130352", "DCM", "Film Holder") +#define CODE_DCM_WinstonLutzPointer DSRBasicCodedEntry("130353", "DCM", "Winston-Lutz Pointer") +#define CODE_DCM_BowtieFilter DSRBasicCodedEntry("130354", "DCM", "Bowtie Filter") +#define CODE_DCM_FlatteningFilterBeam DSRBasicCodedEntry("130355", "DCM", "Flattening Filter Beam") +#define CODE_DCM_NonFlatteningFilterBeam DSRBasicCodedEntry("130356", "DCM", "Non-Flattening Filter Beam") +#define CODE_DCM_PartialFlatteningFilterBeam DSRBasicCodedEntry("130357", "DCM", "Partial Flattening Filter Beam") +#define CODE_DCM_PhysicsAssistant DSRBasicCodedEntry("128678", "DCM", "Physics Assistant") +#define CODE_DCM_NominalRadiationSourceLocation DSRBasicCodedEntry("130358", "DCM", "Nominal Radiation Source Location") +#define CODE_DCM_TreatmentMachineIsocenter DSRBasicCodedEntry("130359", "DCM", "Treatment Machine Isocenter") +#define CODE_DCM_FixedLaserSetupPoint DSRBasicCodedEntry("130360", "DCM", "Fixed Laser Setup Point") +#define CODE_DCM_RadiotherapyTreatmentDevice DSRBasicCodedEntry("130361", "DCM", "Radiotherapy Treatment Device") +#define CODE_DCM_HeadNodeSet DSRBasicCodedEntry("130362", "DCM", "Head Node Set") +#define CODE_DCM_BodyNodeSet DSRBasicCodedEntry("130363", "DCM", "Body Node Set") +#define CODE_DCM_TrigeminalNodeSet DSRBasicCodedEntry("130364", "DCM", "Trigeminal Node Set") +#define CODE_DCM_QANodePair DSRBasicCodedEntry("130365", "DCM", "QA Node Pair") +#define CODE_DCM_QANode DSRBasicCodedEntry("130366", "DCM", "QA Node") +#define CODE_DCM_RTVRendition DSRBasicCodedEntry("130370", "DCM", "RTV Rendition") +#define CODE_DCM_RTVAudioAndVideoRendition DSRBasicCodedEntry("130371", "DCM", "RTV Audio and Video Rendition") +#define CODE_DCM_RTVStereoVideoRendition DSRBasicCodedEntry("130372", "DCM", "RTV Stereo Video Rendition") +#define CODE_DCM_RTVAudioAndStereoVideoRendition DSRBasicCodedEntry("130373", "DCM", "RTV Audio and Stereo Video Rendition") +#define CODE_DCM_GeometricPurposeOfRegion DSRBasicCodedEntry("130400", "DCM", "Geometric purpose of region") +#define CODE_DCM_VisualExplanation DSRBasicCodedEntry("130401", "DCM", "Visual explanation") +#define CODE_DCM_ClassActivation DSRBasicCodedEntry("130402", "DCM", "Class activation") +#define CODE_DCM_GradientWeightedClassActivation DSRBasicCodedEntry("130403", "DCM", "Gradient-weighted class activation") +#define CODE_DCM_Saliency DSRBasicCodedEntry("130404", "DCM", "Saliency") +#define CODE_DCM_PatientAttachedDoseControlObject DSRBasicCodedEntry("130405", "DCM", "Patient-Attached Dose Control Object") +#define CODE_DCM_NonUterineLeiomyosarcoma DSRBasicCodedEntry("130406", "DCM", "Non-uterine leiomyosarcoma") +#define CODE_DCM_BoneAndSoftTissue DSRBasicCodedEntry("130407", "DCM", "Bone and soft tissue") +#define CODE_DCM_PerivascularAdiposeTissueFatAttenuationIndex DSRBasicCodedEntry("130408", "DCM", "Perivascular adipose tissue fat attenuation index") +#define CODE_DCM_PatientPosition DSRBasicCodedEntry("130410", "DCM", "Patient position") +#define CODE_DCM_PatientRotationLongitudinal DSRBasicCodedEntry("130411", "DCM", "Patient rotation longitudinal") +#define CODE_DCM_PatientElevation DSRBasicCodedEntry("130412", "DCM", "Patient elevation") +#define CODE_DCM_HyperventilationBegin DSRBasicCodedEntry("130413", "DCM", "Hyperventilation begin") +#define CODE_DCM_HyperventilationEnd DSRBasicCodedEntry("130414", "DCM", "Hyperventilation end") +#define CODE_DCM_PostHyperventilation DSRBasicCodedEntry("130415", "DCM", "Post-hyperventilation") +#define CODE_DCM_AirflowThermistor DSRBasicCodedEntry("130416", "DCM", "Airflow Thermistor") +#define CODE_DCM_AirflowThermocouple DSRBasicCodedEntry("130417", "DCM", "Airflow Thermocouple") +#define CODE_DCM_AirflowNasalProng DSRBasicCodedEntry("130418", "DCM", "Airflow Nasal Prong") +#define CODE_DCM_AirflowPVDF DSRBasicCodedEntry("130419", "DCM", "Airflow PVDF") +#define CODE_DCM_AirflowCPAP DSRBasicCodedEntry("130420", "DCM", "Airflow CPAP") +#define CODE_DCM_Airflow DSRBasicCodedEntry("130421", "DCM", "Airflow") +#define CODE_DCM_PAPPressure DSRBasicCodedEntry("130422", "DCM", "PAP Pressure") +#define CODE_DCM_PAPLeakPressure DSRBasicCodedEntry("130423", "DCM", "PAP Leak Pressure") +#define CODE_DCM_PAPTidalVolume DSRBasicCodedEntry("130424", "DCM", "PAP Tidal Volume") +#define CODE_DCM_EsophagealPressure DSRBasicCodedEntry("130425", "DCM", "Esophageal Pressure") +#define CODE_DCM_RespiratoryPressure DSRBasicCodedEntry("130426", "DCM", "Respiratory Pressure") +#define CODE_DCM_ThoracicRespiratoryInductance DSRBasicCodedEntry("130427", "DCM", "Thoracic Respiratory Inductance") +#define CODE_DCM_AbdominalRespiratoryInductance DSRBasicCodedEntry("130428", "DCM", "Abdominal Respiratory Inductance") +#define CODE_DCM_ThoracicRespiratoryPVDF DSRBasicCodedEntry("130429", "DCM", "Thoracic Respiratory PVDF") +#define CODE_DCM_AbdominalRespiratoryPVDF DSRBasicCodedEntry("130430", "DCM", "Abdominal Respiratory PVDF") +#define CODE_DCM_ThoracicRespiratoryEffort DSRBasicCodedEntry("130431", "DCM", "Thoracic Respiratory Effort") +#define CODE_DCM_AbdominalRespiratoryEffort DSRBasicCodedEntry("130432", "DCM", "Abdominal Respiratory Effort") +#define CODE_DCM_RespiratoryEffort DSRBasicCodedEntry("130433", "DCM", "Respiratory Effort") +#define CODE_DCM_CO2Transcutaneous DSRBasicCodedEntry("130434", "DCM", "CO2 Transcutaneous") +#define CODE_DCM_CO2WaveformEndTidalMainStream DSRBasicCodedEntry("130435", "DCM", "CO2 Waveform End-tidal Main-stream") +#define CODE_DCM_CO2TrendEndTidalMainStream DSRBasicCodedEntry("130436", "DCM", "CO2 Trend End-tidal Main-stream") +#define CODE_DCM_CO2WaveformEndTidalSideStream DSRBasicCodedEntry("130437", "DCM", "CO2 Waveform End-tidal Side-stream") +#define CODE_DCM_CO2TrendEndTidalSideStream DSRBasicCodedEntry("130438", "DCM", "CO2 Trend End-tidal Side-stream") +#define CODE_DCM_CO2WaveformMainStream DSRBasicCodedEntry("130439", "DCM", "CO2 Waveform Main-stream") +#define CODE_DCM_CO2WaveformSideStream DSRBasicCodedEntry("130440", "DCM", "CO2 Waveform Side-stream") +#define CODE_DCM_CO2TrendMainStream DSRBasicCodedEntry("130441", "DCM", "CO2 Trend Main-stream") +#define CODE_DCM_CO2TrendSideStream DSRBasicCodedEntry("130442", "DCM", "CO2 Trend Side-stream") +#define CODE_DCM_CO2Respiration DSRBasicCodedEntry("130443", "DCM", "CO2 Respiration") +#define CODE_DCM_RTTreatmentWithAdHocPlanning DSRBasicCodedEntry("130444", "DCM", "RT Treatment with Ad Hoc Planning") +#define CODE_DCM_ImagingAgentAdministrationStepSequenceNumber DSRBasicCodedEntry("130445", "DCM", "Imaging Agent Administration Step Sequence Number") +#define CODE_DCM_OperatorDecisionToTerminateTreatment DSRBasicCodedEntry("130450", "DCM", "Operator decision to terminate treatment") +#define CODE_DCM_PatientDecisionToTerminateTreatment DSRBasicCodedEntry("130451", "DCM", "Patient decision to terminate treatment") +#define CODE_DCM_PhysicianDecisionToTerminateTreatment DSRBasicCodedEntry("130452", "DCM", "Physician decision to terminate treatment") +#define CODE_DCM_TreatmentTerminated DSRBasicCodedEntry("130453", "DCM", "Treatment Terminated") +#define CODE_DCM_ResolvedByOverridingInterlock DSRBasicCodedEntry("130454", "DCM", "Resolved by overriding Interlock") +#define CODE_DCM_ResolvedByRepositioningPatient DSRBasicCodedEntry("130455", "DCM", "Resolved by repositioning Patient") +#define CODE_DCM_BolusPresent DSRBasicCodedEntry("130456", "DCM", "Bolus Present") +#define CODE_DCM_ConePresent DSRBasicCodedEntry("130457", "DCM", "Cone Present") +#define CODE_DCM_BlockPresent DSRBasicCodedEntry("130458", "DCM", "Block Present") +#define CODE_DCM_ApplicatorPresent DSRBasicCodedEntry("130459", "DCM", "Applicator Present") +#define CODE_DCM_HeadframePresent DSRBasicCodedEntry("130460", "DCM", "Headframe Present") +#define CODE_DCM_InappropriatePatientOrientation DSRBasicCodedEntry("130461", "DCM", "Inappropriate Patient Orientation") +#define CODE_DCM_InappropriatePatientPosition DSRBasicCodedEntry("130462", "DCM", "Inappropriate Patient Position") +#define CODE_DCM_MachineNotAvailable DSRBasicCodedEntry("130463", "DCM", "Machine Not Available") +#define CODE_DCM_ChangeInPatientAnatomy DSRBasicCodedEntry("130464", "DCM", "Change in Patient Anatomy") +#define CODE_DCM_MachineCalibrationAdjustment DSRBasicCodedEntry("130465", "DCM", "Machine Calibration Adjustment") +#define CODE_DCM_UnavailabilityOfABeamModifier DSRBasicCodedEntry("130466", "DCM", "Unavailability of a Beam Modifier") +#define CODE_DCM_MachineCapabilityLicenseExpired DSRBasicCodedEntry("130467", "DCM", "Machine Capability License Expired") +#define CODE_DCM_BeamTargetingToleranceViolation DSRBasicCodedEntry("130468", "DCM", "Beam Targeting Tolerance Violation") +#define CODE_DCM_MetersetToleranceViolation DSRBasicCodedEntry("130469", "DCM", "Meterset Tolerance Violation") +#define CODE_DCM_DeliveryRateToleranceViolation DSRBasicCodedEntry("130470", "DCM", "Delivery Rate Tolerance Violation") +#define CODE_DCM_JawPositionToleranceViolation DSRBasicCodedEntry("130471", "DCM", "Jaw Position Tolerance Violation") +#define CODE_DCM_MLCPositionToleranceViolation DSRBasicCodedEntry("130472", "DCM", "MLC Position Tolerance Violation") +#define CODE_DCM_SourcePositionToleranceViolation DSRBasicCodedEntry("130473", "DCM", "Source Position Tolerance Violation") +#define CODE_DCM_DoseRateToleranceViolation DSRBasicCodedEntry("130474", "DCM", "Dose Rate Tolerance Violation") +#define CODE_DCM_PrimaryFluenceMonitoringSystemInterlock DSRBasicCodedEntry("130475", "DCM", "Primary Fluence Monitoring System Interlock") +#define CODE_DCM_SecondaryFluenceMonitoringSystemInterlock DSRBasicCodedEntry("130476", "DCM", "Secondary Fluence Monitoring System Interlock") +#define CODE_DCM_TimerInterlock DSRBasicCodedEntry("130477", "DCM", "Timer Interlock") +#define CODE_DCM_DoorInterlock DSRBasicCodedEntry("130478", "DCM", "Door Interlock") +#define CODE_DCM_PatientMotionInterlock DSRBasicCodedEntry("130479", "DCM", "Patient Motion Interlock") +#define CODE_DCM_FamilyHistoryOfNonMelanomaSkinCancer DSRBasicCodedEntry("130480", "DCM", "Family history of non-melanoma skin cancer") +#define CODE_DCM_FamilyHistoryOfMelanomaInSitu DSRBasicCodedEntry("130481", "DCM", "Family history of melanoma in situ") +#define CODE_DCM_HistoryOfNonMelanomaSkinCancer DSRBasicCodedEntry("130482", "DCM", "History of non-melanoma skin cancer") +#define CODE_DCM_NumberOfMalignantMelanomas DSRBasicCodedEntry("130483", "DCM", "Number of malignant melanomas") +#define CODE_DCM_NumberOfMelanomasInSitu DSRBasicCodedEntry("130484", "DCM", "Number of melanomas in situ") +#define CODE_DCM_FirmSkinLesion DSRBasicCodedEntry("130485", "DCM", "Firm skin lesion") +#define CODE_DCM_RaisedSkinLesion DSRBasicCodedEntry("130486", "DCM", "Raised skin lesion") +#define CODE_DCM_NumberOfFirstDegreeRelativesAffectedByMalignantMelanoma DSRBasicCodedEntry("130487", "DCM", "Number of first-degree relatives affected by malignant melanoma") +#define CODE_DCM_RegionInSpace DSRBasicCodedEntry("130488", "DCM", "Region in Space") +#define CODE_DCM_ReferencedRegionOfInterestIdentifier DSRBasicCodedEntry("130489", "DCM", "Referenced Region of Interest Identifier") #endif diff --git a/dcmsr/include/dcmtk/dcmsr/codes/ncit.h b/dcmsr/include/dcmtk/dcmsr/codes/ncit.h index c64cf327..935826df 100644 --- a/dcmsr/include/dcmtk/dcmsr/codes/ncit.h +++ b/dcmsr/include/dcmtk/dcmsr/codes/ncit.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file with NCI Thesaurus Code Definitions (Coding Scheme "NCIt") * - * Generated automatically from DICOM PS 3.16-2019c - * File created on 2019-06-19 17:38:36 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 10:55:26 by J. Riesmeier * */ @@ -34,7 +34,7 @@ * code definitions * *--------------------*/ -// total number of codes: 36 +// total number of codes: 42 // - retired: 0 // - no name: 0 // - not unique: 0 @@ -54,6 +54,8 @@ #define CODE_NCIt_Technetium99mTrofolastat DSRBasicCodedEntry("C116887", "NCIt", "Technetium^99m Trofolastat") #define CODE_NCIt_PSMA11_Ga68 DSRBasicCodedEntry("C118961", "NCIt", "PSMA-11 Ga^68^") #define CODE_NCIt_Sarcosine_C11 DSRBasicCodedEntry("C122684", "NCIt", "Sarcosine C^11^") +#define CODE_NCIt_SoftTissueSarcoma_excludingRhabdomyosarcoma DSRBasicCodedEntry("C148457", "NCIt", "Soft tissue sarcoma, excluding rhabdomyosarcoma") +#define CODE_NCIt_166Holmium DSRBasicCodedEntry("C1943", "NCIt", "^166^Holmium") #define CODE_NCIt_MouseMammaryFatPad DSRBasicCodedEntry("C22550", "NCIt", "Mouse mammary fat pad") #define CODE_NCIt_Middle DSRBasicCodedEntry("C25569", "NCIt", "Middle") #define CODE_NCIt_Reader DSRBasicCodedEntry("C28747", "NCIt", "Reader") @@ -69,10 +71,12 @@ #define CODE_NCIt_AdverseEvent DSRBasicCodedEntry("C41331", "NCIt", "Adverse Event") #define CODE_NCIt_TemperatureSensorDeviceComponent DSRBasicCodedEntry("C50304", "NCIt", "Temperature sensor device component") #define CODE_NCIt_Reviewer DSRBasicCodedEntry("C54634", "NCIt", "Reviewer") +#define CODE_NCIt_Ion DSRBasicCodedEntry("C597", "NCIt", "Ion") #define CODE_NCIt_AdLibitum DSRBasicCodedEntry("C64636", "NCIt", "ad libitum") #define CODE_NCIt_ActivitySession DSRBasicCodedEntry("C67447", "NCIt", "Activity Session") #define CODE_NCIt_UnitConversionFactor DSRBasicCodedEntry("C70774", "NCIt", "Unit Conversion Factor") #define CODE_NCIt_MedicalProductExpirationDate DSRBasicCodedEntry("C70854", "NCIt", "Medical Product Expiration Date") +#define CODE_NCIt_CardiotonicAgent DSRBasicCodedEntry("C78322", "NCIt", "Cardiotonic agent") #define CODE_NCIt_NonEnhancingLesion DSRBasicCodedEntry("C81175", "NCIt", "Non-Enhancing Lesion") #define CODE_NCIt_Erect DSRBasicCodedEntry("C86043", "NCIt", "erect") #define CODE_NCIt_BeddingChange DSRBasicCodedEntry("C90365", "NCIt", "Bedding change") @@ -81,8 +85,10 @@ #define CODE_NCIt_HousingHumidity DSRBasicCodedEntry("C90395", "NCIt", "Housing humidity") #define CODE_NCIt_LightCycle DSRBasicCodedEntry("C90419", "NCIt", "Light cycle") #define CODE_NCIt_WaterDelivery DSRBasicCodedEntry("C90486", "NCIt", "Water delivery") +#define CODE_NCIt_Dosimetrist DSRBasicCodedEntry("C93176", "NCIt", "Dosimetrist") #define CODE_NCIt_ReferenceRegion DSRBasicCodedEntry("C94970", "NCIt", "Reference Region") #define CODE_NCIt_DCFBC_F18 DSRBasicCodedEntry("C96234", "NCIt", "DCFBC F^18^") #define CODE_NCIt_Adjudicator DSRBasicCodedEntry("C96561", "NCIt", "Adjudicator") +#define CODE_NCIt_Fibrate DSRBasicCodedEntry("C98150", "NCIt", "Fibrate") #endif diff --git a/dcmsr/include/dcmtk/dcmsr/codes/umls.h b/dcmsr/include/dcmtk/dcmsr/codes/umls.h index b6fcb095..a665cf21 100644 --- a/dcmsr/include/dcmtk/dcmsr/codes/umls.h +++ b/dcmsr/include/dcmtk/dcmsr/codes/umls.h @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Header file with UMLS Code Definitions (Coding Scheme "UMLS") * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 16:52:49 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 10:55:25 by J. Riesmeier * */ @@ -74,6 +74,7 @@ #define CODE_UMLS_Fluoroetanidazole_F18 DSRBasicCodedEntry("C1541539", "UMLS", "Fluoroetanidazole F^18^") #define CODE_UMLS_CommercialProduct DSRBasicCodedEntry("C1547887", "UMLS", "Commercial product") #define CODE_UMLS_Antihypoglycemic DSRBasicCodedEntry("C1579431", "UMLS", "Antihypoglycemic") +#define CODE_UMLS_PK11195_11C DSRBasicCodedEntry("C1609883", "UMLS", "PK11195 ^11^C") #define CODE_UMLS_Unscheduled DSRBasicCodedEntry("C1699701", "UMLS", "Unscheduled") #define CODE_UMLS_Nadir DSRBasicCodedEntry("C1708760", "UMLS", "Nadir") #define CODE_UMLS_MedicalPhysicist DSRBasicCodedEntry("C1708969", "UMLS", "Medical Physicist") @@ -96,7 +97,6 @@ #define CODE_UMLS_THK5351_F18 DSRBasicCodedEntry("C4279748", "UMLS", "THK5351 F^18^") #define CODE_UMLS_MK6240_F18 DSRBasicCodedEntry("C4506764", "UMLS", "MK-6240 F^18^") #define CODE_UMLS_UCBJ_C11 DSRBasicCodedEntry("C4506788", "UMLS", "UCB-J C^11^") -#define CODE_UMLS_Flortaucipir_F18 DSRBasicCodedEntry("C4547429", "UMLS", "Flortaucipir F^18^") #define CODE_UMLS_THK5317_F18 DSRBasicCodedEntry("C4550127", "UMLS", "THK5317 F^18^") #endif diff --git a/dcmsr/include/dcmtk/dcmsr/dsrdoc.h b/dcmsr/include/dcmtk/dcmsr/dsrdoc.h index b61fc6cb..83172e7a 100644 --- a/dcmsr/include/dcmtk/dcmsr/dsrdoc.h +++ b/dcmsr/include/dcmtk/dcmsr/dsrdoc.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2019, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -263,7 +263,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument virtual OFCondition setSpecificCharacterSetType(const E_CharacterSet characterSet); /** get document preliminary flag. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return preliminary flag (might be DSRTypes::PF_invalid if not specified) */ virtual E_PreliminaryFlag getPreliminaryFlag() const; @@ -271,7 +271,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument /** set document preliminary flag. * According to the DICOM standard, the concept of "completeness" is independent of the * concept of "preliminary" or "final". Therefore, this flag can be specified separately. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param flag preliminary flag to be set (use DSRTypes::PF_invalid to omit this optional * value) ** @return status, EC_Normal if successful, an error code otherwise @@ -281,19 +281,19 @@ class DCMTK_DCMSR_EXPORT DSRDocument /** get document completion flag. * According to the DICOM standard, this flag describes the estimated degree of completeness * of an SR Document. See DICOM standard for details. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return completion flag (might be DSRTypes::CF_invalid if read from dataset) */ virtual E_CompletionFlag getCompletionFlag() const; /** get document verification flag. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return verification flag (might be DSRTypes::VF_invalid if read from dataset) */ virtual E_VerificationFlag getVerificationFlag() const; /** check whether there are one or more verifying observers. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return OFTrue if there is at least one verifying observer, OFFalse otherwise */ virtual OFBool hasVerifyingObservers() const; @@ -302,7 +302,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * A document can be verified more than once. The verification flag should be VERIFIED * if any verifying observer is specified. The details on the observer can be retrieved * using the getVerifyingObserver() methods. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return number of verifying observers (if any), 0 otherwise */ virtual size_t getNumberOfVerifyingObservers() const; @@ -310,7 +310,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument /** get information about a verifying observer. * All reference variables are cleared before the information is retrieved, i.e. if an error * occurs (return value != EC_Normal) non-empty variables do contain valid (empty) data. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param idx index of the verifying observer to be retrieved (starting with 1). * Use getNumberOfVerifyingObservers() to get the maximum value. * @param dateTime reference to variable where the date and time when this document @@ -329,7 +329,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument /** get information about a verifying observer. * All reference variables are cleared before the information is retrieved, i.e. if an error * occurs (return value != EC_Normal) non-empty variables do contain valid (empty) data. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param idx index of the verifying observer to be retrieved (starting with 1). * Use getNumberOfVerifyingObservers() to get the maximum value. * @param dateTime reference to variable where the date and time when this document @@ -357,7 +357,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * included in this document with or without modification." and "[...] the use of the * Predecessor Document Sequence allows tracing back to the input SR Document, which in this * case is the previous version." - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return reference to list object */ virtual DSRSOPInstanceReferenceList &getPredecessorDocuments(); @@ -398,7 +398,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * reference all other evidence considered pertinent for this SR Document that is not listed * in the Current Requested Procedure Evidence Sequence. This requires that the same SOP * Instance shall not be referenced in both of these Sequences." - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return reference to list object */ virtual DSRSOPInstanceReferenceList &getPertinentOtherEvidence(); @@ -411,7 +411,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * Group 7006 (SR Document Purposes of Reference). * Note: An equivalent rendering of the document might be provided as an "Encapsulated PDF" * DICOM object. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return reference to list object */ virtual DSRReferencedInstanceList &getReferencedInstances(); @@ -435,7 +435,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument const signed long pos = 0) const; /** get completion flag description. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param value reference to variable in which the value should be stored * @param pos index of the value to get (0..vm-1), -1 for all components ** @return status, EC_Normal if successful, an error code otherwise @@ -740,7 +740,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument const OFBool check = OFTrue); /** set completion flag description. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param value explanation of the value that is set for completion flag. If an empty * string is passed, the description is removed from the dataset (type 3). * @param check check 'value' for conformance with VR (LO) and VM (1) if enabled @@ -1061,7 +1061,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * reset (OFFalse). The preliminary flag is not modified by this method. Also the * various lists of referenced instances remain unchanged, i.e. they have to be * adapted manually if needed. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. * @param clearList clear list of predecessor documents before adding the current * document if OFTrue. Append current document to existing list * otherwise. @@ -1074,7 +1074,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * describes the estimated degree of completeness of an SR Document (see DICOM standard * for details). The completion flag description is set to an empty string (i.e. absent * in DICOM dataset). - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @return status, EC_Normal if successful, an error code otherwise */ virtual OFCondition completeDocument(); @@ -1084,7 +1084,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * describes the estimated degree of completeness of an SR Document (see DICOM standard * for details). The completion flag description can be modified independently from the * flag by means of the method setCompletionFlagDescription() - see above. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param description explanation of the value set for completion flag. * (optional, see previous method, VR=LO) * @param check check 'description' for conformance with VR and VM if enabled @@ -1100,7 +1100,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * Please note that only completed documents (see completion flag) can be verified and that * a new SOP instance UID has to be generated (manually) according to the DICOM standard when * creating a dataset/file from this document. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param observerName name of the person who has verified this document (required, VR=PN) * @param organization name of the organization to which the observer belongs (required, VR=LO) * @param dateTime verification date time (optional). If empty/absent the current date and @@ -1121,7 +1121,7 @@ class DCMTK_DCMSR_EXPORT DSRDocument * Please note that only completed documents (see completion flag) can be verified and that * a new SOP instance UID has to be generated (manually) according to the DICOM standard when * creating a dataset/file from this document. - * @note Not applicable to Key Object Selection Documents. + * @note Not applicable to document types that use the Key Object Document Module. ** @param observerName name of the person who has verified this document (required, VR=PN) * @param observerCode code identifying the verifying observer (optional, see previous method) * @param organization name of the organization to which the observer belongs (required, VR=LO) @@ -1154,9 +1154,9 @@ class DCMTK_DCMSR_EXPORT DSRDocument * document management functions do reset the flag (i.e. set the FinalizedFlag to OFFalse), * other methods (e.g. setXXX) do not change the flag though the state of the document is * not finalized any more after they have been called. - * @note Not applicable to Key Object Selection Documents since there's no completion flag in - * this type of SR document. Please note that this method has nothing to do with the - * preliminary flag. + * @note Not applicable to document types that use the Key Object Document Module since there + * is no completion flag attribute in this module. Please note that this method has + * nothing to do with the preliminary flag. ** @return status, EC_Normal if successful, an error code otherwise */ virtual OFCondition finalizeDocument(); diff --git a/dcmsr/include/dcmtk/dcmsr/dsrimgvl.h b/dcmsr/include/dcmtk/dcmsr/dsrimgvl.h index 20e7a3c1..0a615fe5 100644 --- a/dcmsr/include/dcmtk/dcmsr/dsrimgvl.h +++ b/dcmsr/include/dcmtk/dcmsr/dsrimgvl.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2018, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -441,7 +441,7 @@ class DCMTK_DCMSR_EXPORT DSRImageReferenceValue /** check the specified SOP class UID for validity. * This method further specializes the checks performed in the base class * DSRCompositeReferenceValue. All image and segmentation SOP classes that - * are defined in DICOM PS 3.6-2017e are allowed. + * are defined in DICOM PS 3.6-2020c are allowed. ** @param sopClassUID SOP class UID to be checked ** @return status, EC_Normal if value is valid, an error code otherwise */ diff --git a/dcmsr/include/dcmtk/dcmsr/dsrrsdcc.h b/dcmsr/include/dcmtk/dcmsr/dsrrsdcc.h new file mode 100644 index 00000000..67044494 --- /dev/null +++ b/dcmsr/include/dcmtk/dcmsr/dsrrsdcc.h @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 2020, J. Riesmeier, Oldenburg, Germany + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsr + * + * Author: Joerg Riesmeier + * + * Purpose: + * classes: DSRRenditionSelectionDocumentConstraintChecker + * + */ + + +#ifndef DSRRSDCC_H +#define DSRRSDCC_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmsr/dsriodcc.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for checking the relationship content constraints of the Rendition Selection + * Document IOD. + * According to DICOM PS 3.3: "The document shall be constructed from TID 2010 (Key + * Object Selection) invoked at the root node." + */ +class DCMTK_DCMSR_EXPORT DSRRenditionSelectionDocumentConstraintChecker + : public DSRIODConstraintChecker +{ + + public: + + /** default constructor + */ + DSRRenditionSelectionDocumentConstraintChecker(); + + /** destructor + */ + virtual ~DSRRenditionSelectionDocumentConstraintChecker(); + + /** check whether by-reference relationships are allowed for this SR IOD + ** @return always returns OFFalse, i.e. by-reference relationships are not allowed + */ + virtual OFBool isByReferenceAllowed() const; + + /** check whether this SR IOD requires template support + ** @return always returns OFTrue, i.e. template support is required + */ + virtual OFBool isTemplateSupportRequired() const; + + /** get identifier and mapping resource of the root template (if any) + ** @param templateIdentifier identifier of the root template (might be empty) + * @param mappingResource mapping resource that defines the root template + * (might be empty) + ** @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRootTemplateIdentification(OFString &templateIdentifier, + OFString &mappingResource) const; + + /** get the associated document type of the SR IOD + ** @return document type (DSRTypes::DT_RenditionSelectionDocument) + */ + virtual E_DocumentType getDocumentType() const; + + /** check whether specified content relationship is allowed for this IOD + ** @param sourceValueType value type of the source content item to be checked + * @param relationshipType type of relationship between source and target item + * @param targetValueType value type of the target content item to be checked + * @param byReference optional flag indicating whether the node/relationship + * should be added by-value (default) or by-reference + ** @return OFTrue if content relationship is allowed, OFFalse otherwise + */ + virtual OFBool checkContentRelationship(const E_ValueType sourceValueType, + const E_RelationshipType relationshipType, + const E_ValueType targetValueType, + const OFBool byReference = OFFalse) const; +}; + + +#endif diff --git a/dcmsr/include/dcmtk/dcmsr/dsrtypes.h b/dcmsr/include/dcmtk/dcmsr/dsrtypes.h index d3915ac9..190b3fc5 100644 --- a/dcmsr/include/dcmtk/dcmsr/dsrtypes.h +++ b/dcmsr/include/dcmtk/dcmsr/dsrtypes.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2019, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -495,7 +495,7 @@ class DCMTK_DCMSR_EXPORT DSRTypes // --- type definitions --- - /** SR document types + /** SR document types (DICOM IOD) */ enum E_DocumentType { @@ -543,8 +543,10 @@ class DCMTK_DCMSR_EXPORT DSRTypes DT_PerformedImagingAgentAdministrationSR, /// DICOM IOD: Planned Imaging Agent Administration SR DT_PlannedImagingAgentAdministrationSR, + /// DICOM IOD: Rendition Selection Document + DT_RenditionSelectionDocument, /// internal type used to mark the last entry - DT_last = DT_PlannedImagingAgentAdministrationSR + DT_last = DT_RenditionSelectionDocument }; /** SR relationship types @@ -893,24 +895,52 @@ class DCMTK_DCMSR_EXPORT DSRTypes static const char *documentTypeToDocumentTitle(const E_DocumentType documentType, OFString &documentTitle); - /** check whether SR document type requires Enhanced General Equipment Module + /** check whether a given SR document type requires the Enhanced General Equipment Module ** @param documentType SR document type to be checked - ** @return OFTrue if Enhanced General Equipment Module is required, OFFalse otherwise + ** @return OFTrue if the Enhanced General Equipment Module is required, OFFalse otherwise */ static OFBool requiresEnhancedEquipmentModule(const E_DocumentType documentType); - /** check whether SR document type requires Timezone Module + /** check whether a given SR document type requires the Timezone Module ** @param documentType SR document type to be checked - ** @return OFTrue if Timezone Module is required, OFFalse otherwise + ** @return OFTrue if the Timezone Module is required, OFFalse otherwise */ static OFBool requiresTimezoneModule(const E_DocumentType documentType); - /** check whether SR document type requires Synchronization Module + /** check whether a given SR document type requires the Synchronization Module ** @param documentType SR document type to be checked - ** @return OFTrue if Synchronization Module is required, OFFalse otherwise + ** @return OFTrue if the Synchronization Module is required, OFFalse otherwise */ static OFBool requiresSynchronizationModule(const E_DocumentType documentType); + /** check whether a given SR document type uses the SR Document Series Module + * (instead of the Key Object Document Series Module) + ** @param documentType SR document type to be checked + ** @return OFTrue if the SR Document Series Module is used, OFFalse otherwise + */ + static OFBool usesSRDocumentSeriesModule(const E_DocumentType documentType); + + /** check whether a given SR document type uses the Key Object Document Series Module + * (instead of the SR Document Series Module) + ** @param documentType SR document type to be checked + ** @return OFTrue if the Key Object Document Series Module is used, OFFalse otherwise + */ + static OFBool usesKeyObjectDocumentSeriesModule(const E_DocumentType documentType); + + /** check whether a given SR document type uses the SR Document General Module + * (instead of the Key Object Document Module) + ** @param documentType SR document type to be checked + ** @return OFTrue if the SR Document General Module is used, OFFalse otherwise + */ + static OFBool usesSRDocumentGeneralModule(const E_DocumentType documentType); + + /** check whether a given SR document type uses the Key Object Document Module + * (instead of the SR Document General Module) + ** @param documentType SR document type to be checked + ** @return OFTrue if the Key Object Document Module is used, OFFalse otherwise + */ + static OFBool usesKeyObjectDocumentModule(const E_DocumentType documentType); + /** convert relationship type to DICOM defined term ** @param relationshipType relationship type to be converted ** @return defined term if type is valid, empty string otherwise (never NULL) diff --git a/dcmsr/include/dcmtk/dcmsr/dsrwavvl.h b/dcmsr/include/dcmtk/dcmsr/dsrwavvl.h index c8b457d2..a85cf243 100644 --- a/dcmsr/include/dcmtk/dcmsr/dsrwavvl.h +++ b/dcmsr/include/dcmtk/dcmsr/dsrwavvl.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2018, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -216,7 +216,7 @@ class DCMTK_DCMSR_EXPORT DSRWaveformReferenceValue /** check the specified SOP class UID for validity. * This method further specializes the checks performed in the base class * DSRCompositeReferenceValue. All waveform SOP classes that are defined - * in DICOM PS 3.6-2017e are allowed. + * in DICOM PS 3.6-2020c are allowed. ** @param sopClassUID SOP class UID to be checked ** @return status, EC_Normal if value is valid, an error code otherwise */ diff --git a/dcmsr/include/dcmtk/dcmsr/dsrxmld.h b/dcmsr/include/dcmtk/dcmsr/dsrxmld.h index 5b0880b5..f5217ad7 100644 --- a/dcmsr/include/dcmtk/dcmsr/dsrxmld.h +++ b/dcmsr/include/dcmtk/dcmsr/dsrxmld.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2003-2019, OFFIS e.V. + * Copyright (C) 2003-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -125,8 +125,8 @@ class DCMTK_DCMSR_EXPORT DSRXMLDocument * deep search is performed. ** @param cursor cursor pointing to the node where to start from * @param name name of the node (XML element) to be searched for - * @param required flag specifying whether the node is required or not. If the node - * is required to be present an error message is reported. + * @param required flag specifying whether the node is required or not. If the node is + * required to be present, an error message is reported if necessary. ** @return cursor pointing to the named node if successful, invalid cursor otherwise */ DSRXMLCursor getNamedNode(const DSRXMLCursor &cursor, @@ -138,8 +138,8 @@ class DCMTK_DCMSR_EXPORT DSRXMLDocument * one, i.e. no deep search is performed. ** @param cursor cursor pointing to the parent of the node where to start from * @param name name of the node (XML element) to be searched for - * @param required flag specifying whether the node is required or not. If the node - * is required to be present an error message is reported. + * @param required flag specifying whether the node is required or not. If the node is + * required to be present, an error message is reported if necessary. ** @return cursor pointing to the named node if successful, invalid cursor otherwise */ DSRXMLCursor getNamedChildNode(const DSRXMLCursor &cursor, diff --git a/dcmsr/libcmr/cid100.cc b/dcmsr/libcmr/cid100.cc index b9016c9f..ace0841a 100644 --- a/dcmsr/libcmr/cid100.cc +++ b/dcmsr/libcmr/cid100.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID100_QuantitativeDiagnosticImagingProcedures * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:14 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:49 by J. Riesmeier * */ @@ -18,7 +18,7 @@ // general information on CID 100 (Quantitative Diagnostic Imaging Procedures) #define CONTEXT_GROUP_NUMBER "100" -#define CONTEXT_GROUP_VERSION "20190121" +#define CONTEXT_GROUP_VERSION "20190817" #define CONTEXT_GROUP_UID "1.2.840.10008.6.1.998" #define CONTEXT_GROUP_TYPE OFTrue /* extensible */ @@ -162,7 +162,7 @@ CID100_QuantitativeDiagnosticImagingProcedures::CodeList &CID100_QuantitativeDia Codes->insert(OFMake_pair(PETUnspecifiedBodyRegion, DSRBasicCodedEntry("44136-0", "LN", "PET unspecified body region"))); Codes->insert(OFMake_pair(PETWholeBody, DSRBasicCodedEntry("44139-4", "LN", "PET whole body"))); Codes->insert(OFMake_pair(PETCT_FDGImagingOfWholeBody, DSRBasicCodedEntry("443271005", "SCT", "PET/CT FDG imaging of whole body"))); - Codes->insert(OFMake_pair(PETCT_METImagingOfWholeBody, DSRBasicCodedEntry("443844003", "SCT", "PET/CT MET imaging of whole body"))); + Codes->insert(OFMake_pair(PETCT_METImagingOfWholeBody, DSRBasicCodedEntry("764704008", "SCT", "PET/CT MET imaging of whole body"))); Codes->insert(OFMake_pair(CTPerfusionHeadWithContrastIV, DSRBasicCodedEntry("39142-5", "LN", "CT perfusion head with contrast IV"))); Codes->insert(OFMake_pair(SPECTBrain, DSRBasicCodedEntry("39632-5", "LN", "SPECT brain"))); Codes->insert(OFMake_pair(NMHeadPerfusionBrainPET_CT_AV45, DSRBasicCodedEntry("RPID5427", "RADLEX", "NM head perfusion brain PET-CT AV-45"))); diff --git a/dcmsr/libcmr/cid10013.cc b/dcmsr/libcmr/cid10013.cc index 30ff20cb..b5b15172 100644 --- a/dcmsr/libcmr/cid10013.cc +++ b/dcmsr/libcmr/cid10013.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID10013_CTAcquisitionType * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:39 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:16 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid10033.cc b/dcmsr/libcmr/cid10033.cc index 1839856f..45940351 100644 --- a/dcmsr/libcmr/cid10033.cc +++ b/dcmsr/libcmr/cid10033.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID10033_CTReconstructionAlgorithm * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:41 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:18 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid11.cc b/dcmsr/libcmr/cid11.cc index 26280725..3819068c 100644 --- a/dcmsr/libcmr/cid11.cc +++ b/dcmsr/libcmr/cid11.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID11_RouteOfAdministration * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:09 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:44 by J. Riesmeier * */ @@ -18,7 +18,7 @@ // general information on CID 11 (Route of Administration) #define CONTEXT_GROUP_NUMBER "11" -#define CONTEXT_GROUP_VERSION "20160314" +#define CONTEXT_GROUP_VERSION "20200117" #define CONTEXT_GROUP_UID "1.2.840.10008.6.1.9" #define CONTEXT_GROUP_TYPE OFTrue /* extensible */ @@ -174,6 +174,7 @@ CID11_RouteOfAdministration::CodeList &CID11_RouteOfAdministration::getCodes() Codes->insert(OFMake_pair(NasalRoute, DSRBasicCodedEntry("46713006", "SCT", "Nasal route"))); Codes->insert(OFMake_pair(IntradermalRoute, DSRBasicCodedEntry("372464004", "SCT", "Intradermal route"))); Codes->insert(OFMake_pair(IntratumorRoute, DSRBasicCodedEntry("447122006", "SCT", "Intratumor route"))); + Codes->insert(OFMake_pair(IntracorpusCavernosumRoute, DSRBasicCodedEntry("445769006", "SCT", "Intracorpus cavernosum route"))); } /* should never be NULL */ return *Codes; diff --git a/dcmsr/libcmr/cid244.cc b/dcmsr/libcmr/cid244.cc index 5c306897..44a3a71c 100644 --- a/dcmsr/libcmr/cid244.cc +++ b/dcmsr/libcmr/cid244.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID244_Laterality * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:16 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:51 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid29.cc b/dcmsr/libcmr/cid29.cc index cada2dd6..5f4fe300 100644 --- a/dcmsr/libcmr/cid29.cc +++ b/dcmsr/libcmr/cid29.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID29_AcquisitionModality * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:11 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:45 by J. Riesmeier * */ @@ -18,7 +18,7 @@ // general information on CID 29 (Acquisition Modality) #define CONTEXT_GROUP_NUMBER "29" -#define CONTEXT_GROUP_VERSION "20190327" +#define CONTEXT_GROUP_VERSION "20201115" #define CONTEXT_GROUP_UID "1.2.840.10008.6.1.19" #define CONTEXT_GROUP_TYPE OFTrue /* extensible */ @@ -150,49 +150,54 @@ CID29_AcquisitionModality::CodeList &CID29_AcquisitionModality::getCodes() Codes = new CodeList(); /* and initialize it by adding the coded entries */ Codes->insert(OFMake_pair(Autorefraction, DSRBasicCodedEntry("AR", "DCM", "Autorefraction"))); - Codes->insert(OFMake_pair(UltrasoundBoneDensitometry, DSRBasicCodedEntry("BDUS", "DCM", "Ultrasound Bone Densitometry"))); Codes->insert(OFMake_pair(BiomagneticImaging, DSRBasicCodedEntry("BI", "DCM", "Biomagnetic Imaging"))); Codes->insert(OFMake_pair(BoneMineralDensitometry, DSRBasicCodedEntry("BMD", "DCM", "Bone Mineral Densitometry"))); + Codes->insert(OFMake_pair(CardiacElectrophysiology, DSRBasicCodedEntry("EPS", "DCM", "Cardiac Electrophysiology"))); Codes->insert(OFMake_pair(ComputedRadiography, DSRBasicCodedEntry("CR", "DCM", "Computed Radiography"))); Codes->insert(OFMake_pair(ComputedTomography, DSRBasicCodedEntry("CT", "DCM", "Computed Tomography"))); + Codes->insert(OFMake_pair(Dermoscopy, DSRBasicCodedEntry("DMS", "DCM", "Dermoscopy"))); Codes->insert(OFMake_pair(Diaphanography, DSRBasicCodedEntry("DG", "DCM", "Diaphanography"))); Codes->insert(OFMake_pair(DigitalRadiography, DSRBasicCodedEntry("DX", "DCM", "Digital Radiography"))); Codes->insert(OFMake_pair(Electrocardiography, DSRBasicCodedEntry("ECG", "DCM", "Electrocardiography"))); - Codes->insert(OFMake_pair(CardiacElectrophysiology, DSRBasicCodedEntry("EPS", "DCM", "Cardiac Electrophysiology"))); + Codes->insert(OFMake_pair(Electroencephalography, DSRBasicCodedEntry("EEG", "DCM", "Electroencephalography"))); + Codes->insert(OFMake_pair(Electromyography, DSRBasicCodedEntry("EMG", "DCM", "Electromyography"))); + Codes->insert(OFMake_pair(Electrooculography, DSRBasicCodedEntry("EOG", "DCM", "Electrooculography"))); Codes->insert(OFMake_pair(Endoscopy, DSRBasicCodedEntry("ES", "DCM", "Endoscopy"))); + Codes->insert(OFMake_pair(ExternalCameraPhotography, DSRBasicCodedEntry("XC", "DCM", "External-camera Photography"))); Codes->insert(OFMake_pair(GeneralMicroscopy, DSRBasicCodedEntry("GM", "DCM", "General Microscopy"))); Codes->insert(OFMake_pair(HemodynamicWaveform, DSRBasicCodedEntry("HD", "DCM", "Hemodynamic Waveform"))); Codes->insert(OFMake_pair(IntraOralRadiography, DSRBasicCodedEntry("IO", "DCM", "Intra-oral Radiography"))); Codes->insert(OFMake_pair(IntravascularOpticalCoherenceTomography, DSRBasicCodedEntry("IVOCT", "DCM", "Intravascular Optical Coherence Tomography"))); Codes->insert(OFMake_pair(IntravascularUltrasound, DSRBasicCodedEntry("IVUS", "DCM", "Intravascular Ultrasound"))); Codes->insert(OFMake_pair(Keratometry, DSRBasicCodedEntry("KER", "DCM", "Keratometry"))); - Codes->insert(OFMake_pair(Lensometry, DSRBasicCodedEntry("LEN", "DCM", "Lensometry"))); Codes->insert(OFMake_pair(LaserScan, DSRBasicCodedEntry("LS", "DCM", "Laser Scan"))); - Codes->insert(OFMake_pair(Mammography, DSRBasicCodedEntry("MG", "DCM", "Mammography"))); + Codes->insert(OFMake_pair(Lensometry, DSRBasicCodedEntry("LEN", "DCM", "Lensometry"))); Codes->insert(OFMake_pair(MagneticResonance, DSRBasicCodedEntry("MR", "DCM", "Magnetic Resonance"))); + Codes->insert(OFMake_pair(Mammography, DSRBasicCodedEntry("MG", "DCM", "Mammography"))); Codes->insert(OFMake_pair(NuclearMedicine, DSRBasicCodedEntry("NM", "DCM", "Nuclear Medicine"))); Codes->insert(OFMake_pair(OphthalmicAxialMeasurements, DSRBasicCodedEntry("OAM", "DCM", "Ophthalmic Axial Measurements"))); - Codes->insert(OFMake_pair(OpticalCoherenceTomography, DSRBasicCodedEntry("OCT", "DCM", "Optical Coherence Tomography"))); - Codes->insert(OFMake_pair(OphthalmicPhotography, DSRBasicCodedEntry("OP", "DCM", "Ophthalmic Photography"))); Codes->insert(OFMake_pair(OphthalmicMapping, DSRBasicCodedEntry("OPM", "DCM", "Ophthalmic Mapping"))); + Codes->insert(OFMake_pair(OphthalmicPhotography, DSRBasicCodedEntry("OP", "DCM", "Ophthalmic Photography"))); Codes->insert(OFMake_pair(OphthalmicTomography, DSRBasicCodedEntry("OPT", "DCM", "Ophthalmic Tomography"))); Codes->insert(OFMake_pair(OphthalmicTomographyBScanVolumeAnalysis, DSRBasicCodedEntry("OPTBSV", "DCM", "Ophthalmic Tomography B-scan Volume Analysis"))); Codes->insert(OFMake_pair(OphthalmicTomographyEnFace, DSRBasicCodedEntry("OPTENF", "DCM", "Ophthalmic Tomography En Face"))); Codes->insert(OFMake_pair(OphthalmicVisualField, DSRBasicCodedEntry("OPV", "DCM", "Ophthalmic Visual Field"))); + Codes->insert(OFMake_pair(OpticalCoherenceTomography, DSRBasicCodedEntry("OCT", "DCM", "Optical Coherence Tomography"))); Codes->insert(OFMake_pair(OpticalSurfaceScanner, DSRBasicCodedEntry("OSS", "DCM", "Optical Surface Scanner"))); - Codes->insert(OFMake_pair(PositronEmissionTomography, DSRBasicCodedEntry("PT", "DCM", "Positron emission tomography"))); Codes->insert(OFMake_pair(PanoramicXRay, DSRBasicCodedEntry("PX", "DCM", "Panoramic X-Ray"))); - Codes->insert(OFMake_pair(RespiratoryWaveform, DSRBasicCodedEntry("RESP", "DCM", "Respiratory Waveform"))); + Codes->insert(OFMake_pair(PositionSensor, DSRBasicCodedEntry("POS", "DCM", "Position Sensor"))); + Codes->insert(OFMake_pair(PositronEmissionTomography, DSRBasicCodedEntry("PT", "DCM", "Positron emission tomography"))); Codes->insert(OFMake_pair(Radiofluoroscopy, DSRBasicCodedEntry("RF", "DCM", "Radiofluoroscopy"))); Codes->insert(OFMake_pair(RadiographicImaging, DSRBasicCodedEntry("RG", "DCM", "Radiographic imaging"))); + Codes->insert(OFMake_pair(RespiratoryWaveform, DSRBasicCodedEntry("RESP", "DCM", "Respiratory Waveform"))); Codes->insert(OFMake_pair(RTImage, DSRBasicCodedEntry("RTIMAGE", "DCM", "RT Image"))); Codes->insert(OFMake_pair(SlideMicroscopy, DSRBasicCodedEntry("SM", "DCM", "Slide Microscopy"))); Codes->insert(OFMake_pair(SubjectiveRefraction, DSRBasicCodedEntry("SRF", "DCM", "Subjective Refraction"))); Codes->insert(OFMake_pair(Thermography, DSRBasicCodedEntry("TG", "DCM", "Thermography"))); Codes->insert(OFMake_pair(Ultrasound, DSRBasicCodedEntry("US", "DCM", "Ultrasound"))); + Codes->insert(OFMake_pair(UltrasoundBoneDensitometry, DSRBasicCodedEntry("BDUS", "DCM", "Ultrasound Bone Densitometry"))); Codes->insert(OFMake_pair(VisualAcuity, DSRBasicCodedEntry("VA", "DCM", "Visual Acuity"))); Codes->insert(OFMake_pair(XRayAngiography, DSRBasicCodedEntry("XA", "DCM", "X-Ray Angiography"))); - Codes->insert(OFMake_pair(ExternalCameraPhotography, DSRBasicCodedEntry("XC", "DCM", "External-camera Photography"))); } /* should never be NULL */ return *Codes; diff --git a/dcmsr/libcmr/cid4020.cc b/dcmsr/libcmr/cid4020.cc index f6df7674..bdaaa6bf 100644 --- a/dcmsr/libcmr/cid4020.cc +++ b/dcmsr/libcmr/cid4020.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID4020_PETRadionuclide * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:18 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:55 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid4021.cc b/dcmsr/libcmr/cid4021.cc index abb3ca13..f2384348 100644 --- a/dcmsr/libcmr/cid4021.cc +++ b/dcmsr/libcmr/cid4021.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID4021_PETRadiopharmaceutical * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:20 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:57 by J. Riesmeier * */ @@ -18,7 +18,7 @@ // general information on CID 4021 (PET Radiopharmaceutical) #define CONTEXT_GROUP_NUMBER "4021" -#define CONTEXT_GROUP_VERSION "20190124" +#define CONTEXT_GROUP_VERSION "20201116" #define CONTEXT_GROUP_UID "1.2.840.10008.6.1.305" #define CONTEXT_GROUP_TYPE OFTrue /* extensible */ @@ -149,6 +149,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod /* create a new code list (should never fail) */ Codes = new CodeList(); /* and initialize it by adding the coded entries */ + Codes->insert(OFMake_pair(_18_FluorineFlortaucipir, DSRBasicCodedEntry("C000591008", "MSH", "^18^Fluorine flortaucipir"))); Codes->insert(OFMake_pair(_28H1_89Zr, DSRBasicCodedEntry("126752", "DCM", "28H1 ^89^Zr"))); Codes->insert(OFMake_pair(_2FA_F18, DSRBasicCodedEntry("126713", "DCM", "2FA F^18^"))); Codes->insert(OFMake_pair(_7D12_89Zr, DSRBasicCodedEntry("126751", "DCM", "7D12 ^89^Zr"))); @@ -185,6 +186,8 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(DfFK_89Zr, DSRBasicCodedEntry("126760", "DCM", "Df-FK ^89^Zr"))); Codes->insert(OFMake_pair(DfFKPEG3_89Zr, DSRBasicCodedEntry("126761", "DCM", "Df-FK-PEG(3) ^89^Zr"))); Codes->insert(OFMake_pair(DN30_89Zr, DSRBasicCodedEntry("126747", "DCM", "DN30 ^89^Zr"))); + Codes->insert(OFMake_pair(DPA713_11C, DSRBasicCodedEntry("126765", "DCM", "DPA-713 ^11^C"))); + Codes->insert(OFMake_pair(DPA714_18F, DSRBasicCodedEntry("126766", "DCM", "DPA-714 ^18^F"))); Codes->insert(OFMake_pair(E4G10_89Zr, DSRBasicCodedEntry("126519", "DCM", "E4G10 ^89^Zr"))); Codes->insert(OFMake_pair(Ecromeximab_89Zr, DSRBasicCodedEntry("126732", "DCM", "Ecromeximab ^89^Zr"))); Codes->insert(OFMake_pair(Edotreotide_Ga68, DSRBasicCodedEntry("C2713594", "UMLS", "Edotreotide Ga^68^"))); @@ -194,7 +197,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(FLB457_C11, DSRBasicCodedEntry("126706", "DCM", "FLB 457 C^11^"))); Codes->insert(OFMake_pair(Florbetaben_F18, DSRBasicCodedEntry("712736002", "SCT", "Florbetaben F^18^"))); Codes->insert(OFMake_pair(Florbetapir_F18, DSRBasicCodedEntry("456995000", "SCT", "Florbetapir F^18^"))); - Codes->insert(OFMake_pair(Flortaucipir_F18, DSRBasicCodedEntry("C4547429", "UMLS", "Flortaucipir F^18^"))); + Codes->insert(OFMake_pair(Flortaucipir_F18, DSRBasicCodedEntry("C000591008", "MSH", "Flortaucipir F^18^"))); Codes->insert(OFMake_pair(Flubatine_F18, DSRBasicCodedEntry("126503", "DCM", "Flubatine F^18^"))); Codes->insert(OFMake_pair(Fluciclatide_F18, DSRBasicCodedEntry("456999006", "SCT", "Fluciclatide F^18^"))); Codes->insert(OFMake_pair(Fluciclovine_F18, DSRBasicCodedEntry("457000009", "SCT", "Fluciclovine F^18^"))); @@ -206,7 +209,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(Fluorodeoxyglucose_F18, DSRBasicCodedEntry("35321007", "SCT", "Fluorodeoxyglucose F^18^"))); Codes->insert(OFMake_pair(FluoroestradiolFES_F18, DSRBasicCodedEntry("C1831937", "UMLS", "Fluoroestradiol (FES) F^18^"))); Codes->insert(OFMake_pair(Fluoroetanidazole_F18, DSRBasicCodedEntry("C1541539", "UMLS", "Fluoroetanidazole F^18^"))); - Codes->insert(OFMake_pair(FluoroLDopa_F18, DSRBasicCodedEntry("129500005", "SCT", "Fluoro-L-dopa F^18^"))); + Codes->insert(OFMake_pair(FluoroLDopa_F18, DSRBasicCodedEntry("5811000122108", "SCT", "Fluoro-L-dopa F^18^"))); Codes->insert(OFMake_pair(Fluoromethane_F18, DSRBasicCodedEntry("422763008", "SCT", "Fluoromethane F^18^"))); Codes->insert(OFMake_pair(Fluoromisonidazole_F18, DSRBasicCodedEntry("422598008", "SCT", "Fluoromisonidazole F^18^"))); Codes->insert(OFMake_pair(FluoropropylDihydrotetrabenazineDTBZ_F18, DSRBasicCodedEntry("C2934038", "UMLS", "Fluoropropyl-dihydrotetrabenazine (DTBZ) F^18^"))); @@ -216,7 +219,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(Flutemetamol_F18, DSRBasicCodedEntry("456997008", "SCT", "Flutemetamol F^18^"))); Codes->insert(OFMake_pair(Fresolimumab_89Zr, DSRBasicCodedEntry("126748", "DCM", "Fresolimumab ^89^Zr"))); Codes->insert(OFMake_pair(GA201_89Zr, DSRBasicCodedEntry("126731", "DCM", "GA201 ^89^Zr"))); - Codes->insert(OFMake_pair(Germanium_Ge68, DSRBasicCodedEntry("129516007", "SCT", "Germanium Ge^68^"))); + Codes->insert(OFMake_pair(Germanium_Ge68, DSRBasicCodedEntry("53315004", "SCT", "Germanium Ge^68^"))); Codes->insert(OFMake_pair(GlembatumumabVedotin_89Zr, DSRBasicCodedEntry("126724", "DCM", "Glembatumumab vedotin ^89^Zr"))); Codes->insert(OFMake_pair(Glutamate_N13, DSRBasicCodedEntry("129509006", "SCT", "Glutamate N^13^"))); Codes->insert(OFMake_pair(Glutamine_C11, DSRBasicCodedEntry("126709", "DCM", "Glutamine C^11^"))); @@ -232,7 +235,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(Mogamulizumab_89Zr, DSRBasicCodedEntry("126738", "DCM", "Mogamulizumab ^89^Zr"))); Codes->insert(OFMake_pair(MonoclonalAntibodymAb_64Cu, DSRBasicCodedEntry("126510", "DCM", "Monoclonal Antibody (mAb) ^64^Cu"))); Codes->insert(OFMake_pair(MonoclonalAntibodymAb_89Zr, DSRBasicCodedEntry("126511", "DCM", "Monoclonal Antibody (mAb) ^89^Zr"))); - Codes->insert(OFMake_pair(MonoclonalAntibody_I124, DSRBasicCodedEntry("424874008", "SCT", "Monoclonal antibody I^124^"))); + Codes->insert(OFMake_pair(MonoclonalAntibody_I124, DSRBasicCodedEntry("423249007", "SCT", "Monoclonal antibody I^124^"))); Codes->insert(OFMake_pair(NanocolloidalAlbumin_89Zr, DSRBasicCodedEntry("126753", "DCM", "Nanocolloidal albumin ^89^Zr"))); Codes->insert(OFMake_pair(Nifene_F18, DSRBasicCodedEntry("126714", "DCM", "Nifene F^18^"))); Codes->insert(OFMake_pair(Obinituzimab_89Zr, DSRBasicCodedEntry("126721", "DCM", "Obinituzimab ^89^Zr"))); @@ -244,6 +247,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(Pegdinetanib_89Zr, DSRBasicCodedEntry("126728", "DCM", "Pegdinetanib ^89^Zr"))); Codes->insert(OFMake_pair(PinatuzumabVedotin_89Zr, DSRBasicCodedEntry("126725", "DCM", "Pinatuzumab vedotin ^89^Zr"))); Codes->insert(OFMake_pair(PittsburghCompoundB_C11, DSRBasicCodedEntry("126500", "DCM", "Pittsburgh compound B C^11^"))); + Codes->insert(OFMake_pair(PK11195_11C, DSRBasicCodedEntry("C1609883", "UMLS", "PK11195 ^11^C"))); Codes->insert(OFMake_pair(PolatuzumabVedotin_89Zr, DSRBasicCodedEntry("126726", "DCM", "Polatuzumab vedotin ^89^Zr"))); Codes->insert(OFMake_pair(PSMA1007_F18, DSRBasicCodedEntry("126758", "DCM", "PSMA-1007 F^18^"))); Codes->insert(OFMake_pair(PSMA11_Ga68, DSRBasicCodedEntry("C118961", "NCIt", "PSMA-11 Ga^68^"))); @@ -264,7 +268,7 @@ CID4021_PETRadiopharmaceutical::CodeList &CID4021_PETRadiopharmaceutical::getCod Codes->insert(OFMake_pair(Sarcosine_C11, DSRBasicCodedEntry("C122684", "NCIt", "Sarcosine C^11^"))); Codes->insert(OFMake_pair(SodiumFluoride_F18, DSRBasicCodedEntry("129501009", "SCT", "Sodium fluoride F^18^"))); Codes->insert(OFMake_pair(SodiumIodide_I124, DSRBasicCodedEntry("422980002", "SCT", "Sodium iodide I^124^"))); - Codes->insert(OFMake_pair(Sodium_Na22, DSRBasicCodedEntry("129517003", "SCT", "Sodium Na^22^"))); + Codes->insert(OFMake_pair(Sodium_Na22, DSRBasicCodedEntry("71633006", "SCT", "Sodium Na^22^"))); Codes->insert(OFMake_pair(Spiperone_F18, DSRBasicCodedEntry("129499001", "SCT", "Spiperone F^18^"))); Codes->insert(OFMake_pair(T807_F18, DSRBasicCodedEntry("126502", "DCM", "T807 F^18^"))); Codes->insert(OFMake_pair(THK5317_F18, DSRBasicCodedEntry("C4550127", "UMLS", "THK5317 F^18^"))); diff --git a/dcmsr/libcmr/cid4031.cc b/dcmsr/libcmr/cid4031.cc index f54c759c..f92396b4 100644 --- a/dcmsr/libcmr/cid4031.cc +++ b/dcmsr/libcmr/cid4031.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID4031_CommonAnatomicRegions * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:22 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:59 by J. Riesmeier * */ @@ -18,7 +18,7 @@ // general information on CID 4031 (Common Anatomic Regions) #define CONTEXT_GROUP_NUMBER "4031" -#define CONTEXT_GROUP_VERSION "20170914" +#define CONTEXT_GROUP_VERSION "20200704" #define CONTEXT_GROUP_UID "1.2.840.10008.6.1.308" #define CONTEXT_GROUP_TYPE OFTrue /* extensible */ @@ -149,8 +149,8 @@ CID4031_CommonAnatomicRegions::CodeList &CID4031_CommonAnatomicRegions::getCodes /* create a new code list (should never fail) */ Codes = new CodeList(); /* and initialize it by adding the coded entries */ - Codes->insert(OFMake_pair(Abdomen, DSRBasicCodedEntry("113345001", "SCT", "Abdomen"))); - Codes->insert(OFMake_pair(AbdomenAndPelvis, DSRBasicCodedEntry("416949008", "SCT", "Abdomen and Pelvis"))); + Codes->insert(OFMake_pair(Abdomen, DSRBasicCodedEntry("818981001", "SCT", "Abdomen"))); + Codes->insert(OFMake_pair(AbdomenAndPelvis, DSRBasicCodedEntry("818982008", "SCT", "Abdomen and Pelvis"))); Codes->insert(OFMake_pair(AcromioclavicularJoint, DSRBasicCodedEntry("85856004", "SCT", "Acromioclavicular joint"))); Codes->insert(OFMake_pair(AnkleJoint, DSRBasicCodedEntry("70258002", "SCT", "Ankle joint"))); Codes->insert(OFMake_pair(Anus, DSRBasicCodedEntry("53505006", "SCT", "Anus"))); @@ -164,12 +164,13 @@ CID4031_CommonAnatomicRegions::CodeList &CID4031_CommonAnatomicRegions::getCodes Codes->insert(OFMake_pair(Calcaneus, DSRBasicCodedEntry("80144004", "SCT", "Calcaneus"))); Codes->insert(OFMake_pair(CervicalSpine, DSRBasicCodedEntry("122494005", "SCT", "Cervical spine"))); Codes->insert(OFMake_pair(CervicoThoracicSpine, DSRBasicCodedEntry("297171002", "SCT", "Cervico-thoracic spine"))); - Codes->insert(OFMake_pair(Chest, DSRBasicCodedEntry("51185008", "SCT", "Chest"))); + Codes->insert(OFMake_pair(Chest, DSRBasicCodedEntry("816094009", "SCT", "Chest"))); Codes->insert(OFMake_pair(ChestAndAbdomen, DSRBasicCodedEntry("416550000", "SCT", "Chest and Abdomen"))); Codes->insert(OFMake_pair(ChestAbdomenAndPelvis, DSRBasicCodedEntry("416775004", "SCT", "Chest, Abdomen and Pelvis"))); Codes->insert(OFMake_pair(Clavicle, DSRBasicCodedEntry("51299004", "SCT", "Clavicle"))); Codes->insert(OFMake_pair(Coccyx, DSRBasicCodedEntry("64688005", "SCT", "Coccyx"))); Codes->insert(OFMake_pair(Colon, DSRBasicCodedEntry("71854001", "SCT", "Colon"))); + Codes->insert(OFMake_pair(CommonBileDuct, DSRBasicCodedEntry("79741001", "SCT", "Common bile duct"))); Codes->insert(OFMake_pair(Duodenum, DSRBasicCodedEntry("38848004", "SCT", "Duodenum"))); Codes->insert(OFMake_pair(ElbowJoint, DSRBasicCodedEntry("16953009", "SCT", "Elbow joint"))); Codes->insert(OFMake_pair(EntireBody, DSRBasicCodedEntry("38266002", "SCT", "Entire body"))); @@ -189,7 +190,8 @@ CID4031_CommonAnatomicRegions::CodeList &CID4031_CommonAnatomicRegions::getCodes Codes->insert(OFMake_pair(Head, DSRBasicCodedEntry("69536005", "SCT", "Head"))); Codes->insert(OFMake_pair(HeadAndNeck, DSRBasicCodedEntry("774007", "SCT", "Head and Neck"))); Codes->insert(OFMake_pair(Heart, DSRBasicCodedEntry("80891009", "SCT", "Heart"))); - Codes->insert(OFMake_pair(HipJoint, DSRBasicCodedEntry("29836001", "SCT", "Hip joint"))); + Codes->insert(OFMake_pair(Hip, DSRBasicCodedEntry("29836001", "SCT", "Hip"))); + Codes->insert(OFMake_pair(HipJoint, DSRBasicCodedEntry("24136001", "SCT", "Hip Joint"))); Codes->insert(OFMake_pair(Humerus, DSRBasicCodedEntry("85050009", "SCT", "Humerus"))); Codes->insert(OFMake_pair(Ileum, DSRBasicCodedEntry("34516001", "SCT", "Ileum"))); Codes->insert(OFMake_pair(Ilium, DSRBasicCodedEntry("22356005", "SCT", "Ilium"))); @@ -199,6 +201,7 @@ CID4031_CommonAnatomicRegions::CodeList &CID4031_CommonAnatomicRegions::getCodes Codes->insert(OFMake_pair(Knee, DSRBasicCodedEntry("72696002", "SCT", "Knee"))); Codes->insert(OFMake_pair(LargeIntestine, DSRBasicCodedEntry("14742008", "SCT", "Large intestine"))); Codes->insert(OFMake_pair(Larynx, DSRBasicCodedEntry("4596009", "SCT", "Larynx"))); + Codes->insert(OFMake_pair(LiverAndBiliaryStructure, DSRBasicCodedEntry("303270005", "SCT", "Liver and biliary structure"))); Codes->insert(OFMake_pair(LowerLeg, DSRBasicCodedEntry("30021000", "SCT", "Lower leg"))); Codes->insert(OFMake_pair(LowerLimb, DSRBasicCodedEntry("61685007", "SCT", "Lower limb"))); Codes->insert(OFMake_pair(LumbarSpine, DSRBasicCodedEntry("122496007", "SCT", "Lumbar spine"))); @@ -216,16 +219,19 @@ CID4031_CommonAnatomicRegions::CodeList &CID4031_CommonAnatomicRegions::getCodes Codes->insert(OFMake_pair(NeckChestAbdomenAndPelvis, DSRBasicCodedEntry("416319003", "SCT", "Neck, Chest, Abdomen and Pelvis"))); Codes->insert(OFMake_pair(OpticCanal, DSRBasicCodedEntry("55024004", "SCT", "Optic canal"))); Codes->insert(OFMake_pair(OrbitalStructure, DSRBasicCodedEntry("363654007", "SCT", "Orbital structure"))); + Codes->insert(OFMake_pair(Pancreas, DSRBasicCodedEntry("15776009", "SCT", "Pancreas"))); + Codes->insert(OFMake_pair(PancreaticDuct, DSRBasicCodedEntry("69930009", "SCT", "Pancreatic duct"))); Codes->insert(OFMake_pair(PancreaticDuctAndBileDuctSystems, DSRBasicCodedEntry("110621006", "SCT", "Pancreatic duct and bile duct systems"))); Codes->insert(OFMake_pair(ParanasalSinus, DSRBasicCodedEntry("2095001", "SCT", "Paranasal sinus"))); Codes->insert(OFMake_pair(ParotidGland, DSRBasicCodedEntry("45289007", "SCT", "Parotid gland"))); Codes->insert(OFMake_pair(Patella, DSRBasicCodedEntry("64234005", "SCT", "Patella"))); - Codes->insert(OFMake_pair(Pelvis, DSRBasicCodedEntry("12921003", "SCT", "Pelvis"))); + Codes->insert(OFMake_pair(Pelvis, DSRBasicCodedEntry("816092008", "SCT", "Pelvis"))); Codes->insert(OFMake_pair(PelvisAndLowerExtremities, DSRBasicCodedEntry("416631005", "SCT", "Pelvis and lower extremities"))); Codes->insert(OFMake_pair(Phantom, DSRBasicCodedEntry("113681", "DCM", "Phantom"))); Codes->insert(OFMake_pair(Prostate, DSRBasicCodedEntry("41216001", "SCT", "Prostate"))); Codes->insert(OFMake_pair(Rectum, DSRBasicCodedEntry("34402009", "SCT", "Rectum"))); Codes->insert(OFMake_pair(Rib, DSRBasicCodedEntry("113197003", "SCT", "Rib"))); + Codes->insert(OFMake_pair(SacroCoccygealSpine, DSRBasicCodedEntry("297174005", "SCT", "Sacro-coccygeal Spine"))); Codes->insert(OFMake_pair(SacroiliacJoint, DSRBasicCodedEntry("39723000", "SCT", "Sacroiliac joint"))); Codes->insert(OFMake_pair(Sacrum, DSRBasicCodedEntry("54735007", "SCT", "Sacrum"))); Codes->insert(OFMake_pair(Scapula, DSRBasicCodedEntry("79601000", "SCT", "Scapula"))); diff --git a/dcmsr/libcmr/cid4031e.cc b/dcmsr/libcmr/cid4031e.cc index 6896f7f1..db6f0be7 100644 --- a/dcmsr/libcmr/cid4031e.cc +++ b/dcmsr/libcmr/cid4031e.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2018, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID4031e_CommonAnatomicRegions @@ -30,7 +30,7 @@ struct DefinedTermTypeMapStruct * constant definitions * *------------------------*/ -// mapping extracted from DICOM PS 3.16-2018a Table L-1 +// mapping extracted from DICOM PS 3.16-2020c Table L-1 static const DefinedTermTypeMapStruct DefinedTermTypeMap[] = { @@ -50,6 +50,7 @@ static const DefinedTermTypeMapStruct DefinedTermTypeMap[] = {"CHESTABDPELVIS", CID4031_CommonAnatomicRegions::ChestAbdomenAndPelvis}, {"CLAVICLE", CID4031_CommonAnatomicRegions::Clavicle}, {"COCCYX", CID4031_CommonAnatomicRegions::Coccyx}, + {"COMMONBILEDUCT", CID4031_CommonAnatomicRegions::CommonBileDuct}, {"COLON", CID4031_CommonAnatomicRegions::Colon}, {"DUODENUM", CID4031_CommonAnatomicRegions::Duodenum}, {"ELBOW", CID4031_CommonAnatomicRegions::ElbowJoint}, @@ -90,6 +91,8 @@ static const DefinedTermTypeMapStruct DefinedTermTypeMap[] = {"NECKCHESTABDPELV", CID4031_CommonAnatomicRegions::NeckChestAbdomenAndPelvis}, {"OPTICCANAL", CID4031_CommonAnatomicRegions::OpticCanal}, {"ORBIT", CID4031_CommonAnatomicRegions::OrbitalStructure}, + {"PANCREAS", CID4031_CommonAnatomicRegions::Pancreas}, + {"PANCREATICDUCT", CID4031_CommonAnatomicRegions::PancreaticDuct}, {"PAROTID", CID4031_CommonAnatomicRegions::ParotidGland}, {"PATELLA", CID4031_CommonAnatomicRegions::Patella}, {"PELVIS", CID4031_CommonAnatomicRegions::Pelvis}, diff --git a/dcmsr/libcmr/cid42.cc b/dcmsr/libcmr/cid42.cc index 578937ea..ddd1d1d1 100644 --- a/dcmsr/libcmr/cid42.cc +++ b/dcmsr/libcmr/cid42.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID42_NumericValueQualifier * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:12 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:12:47 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid6147.cc b/dcmsr/libcmr/cid6147.cc index 1e69fee1..a44da5bb 100644 --- a/dcmsr/libcmr/cid6147.cc +++ b/dcmsr/libcmr/cid6147.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID6147_ResponseCriteria * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:24 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:01 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7021.cc b/dcmsr/libcmr/cid7021.cc index e78cf01e..73dba877 100644 --- a/dcmsr/libcmr/cid7021.cc +++ b/dcmsr/libcmr/cid7021.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7021_MeasurementReportDocumentTitles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:26 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:03 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7181.cc b/dcmsr/libcmr/cid7181.cc index 294a9e7e..bdd2db76 100644 --- a/dcmsr/libcmr/cid7181.cc +++ b/dcmsr/libcmr/cid7181.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7181_AbstractMultiDimensionalImageModelComponentUnits * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:28 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:05 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7445.cc b/dcmsr/libcmr/cid7445.cc index 62348b91..c1417c89 100644 --- a/dcmsr/libcmr/cid7445.cc +++ b/dcmsr/libcmr/cid7445.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7445_DeviceParticipatingRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:30 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:06 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7452.cc b/dcmsr/libcmr/cid7452.cc index 86daa4f8..c725c239 100644 --- a/dcmsr/libcmr/cid7452.cc +++ b/dcmsr/libcmr/cid7452.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7452_OrganizationalRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:32 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:08 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7453.cc b/dcmsr/libcmr/cid7453.cc index 4487988b..a48f95c3 100644 --- a/dcmsr/libcmr/cid7453.cc +++ b/dcmsr/libcmr/cid7453.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7453_PerformingRoles * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:33 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:10 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7464.cc b/dcmsr/libcmr/cid7464.cc index a7e1c6d1..af3124fc 100644 --- a/dcmsr/libcmr/cid7464.cc +++ b/dcmsr/libcmr/cid7464.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7464_GeneralRegionOfInterestMeasurementModifiers * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:35 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:12 by J. Riesmeier * */ diff --git a/dcmsr/libcmr/cid7469.cc b/dcmsr/libcmr/cid7469.cc index e47123a7..5ccdd3ba 100644 --- a/dcmsr/libcmr/cid7469.cc +++ b/dcmsr/libcmr/cid7469.cc @@ -1,12 +1,12 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * Source file for class CID7469_GenericIntensityAndSizeMeasurements * - * Generated automatically from DICOM PS 3.16-2019b - * File created on 2019-04-26 17:15:37 by J. Riesmeier + * Generated automatically from DICOM PS 3.16-2020e + * File created on 2020-11-25 11:13:14 by J. Riesmeier * */ @@ -303,6 +303,9 @@ CID7469_GenericIntensityAndSizeMeasurements::CodeList &CID7469_GenericIntensityA Codes->insert(OFMake_pair(Water, DSRBasicCodedEntry("11713004", "SCT", "Water"))); Codes->insert(OFMake_pair(WaterFraction, DSRBasicCodedEntry("129103", "DCM", "Water fraction"))); Codes->insert(OFMake_pair(RelativeLinearStoppingPower, DSRBasicCodedEntry("130086", "DCM", "Relative Linear Stopping Power"))); + Codes->insert(OFMake_pair(ClassActivation, DSRBasicCodedEntry("130402", "DCM", "Class activation"))); + Codes->insert(OFMake_pair(GradientWeightedClassActivation, DSRBasicCodedEntry("130403", "DCM", "Gradient-weighted class activation"))); + Codes->insert(OFMake_pair(Saliency, DSRBasicCodedEntry("130404", "DCM", "Saliency"))); Codes->insert(OFMake_pair(Length, DSRBasicCodedEntry("410668003", "SCT", "Length"))); Codes->insert(OFMake_pair(PathLength, DSRBasicCodedEntry("121211", "DCM", "Path length"))); Codes->insert(OFMake_pair(Distance, DSRBasicCodedEntry("121206", "DCM", "Distance"))); @@ -319,6 +322,7 @@ CID7469_GenericIntensityAndSizeMeasurements::CodeList &CID7469_GenericIntensityA Codes->insert(OFMake_pair(Circumference, DSRBasicCodedEntry("74551000", "SCT", "Circumference"))); Codes->insert(OFMake_pair(DiameterOfCircumscribedCircle, DSRBasicCodedEntry("131192006", "SCT", "Diameter of circumscribed circle"))); Codes->insert(OFMake_pair(Height, DSRBasicCodedEntry("121207", "DCM", "Height"))); + Codes->insert(OFMake_pair(LineSegmentLength, DSRBasicCodedEntry("121227", "DCM", "Line segment length"))); Codes->insert(OFMake_pair(Maximum3DDiameterOfAMesh, DSRBasicCodedEntry("L0JK", "IBSI", "Maximum 3D Diameter of a Mesh"))); Codes->insert(OFMake_pair(MajorAxisIn3DLength, DSRBasicCodedEntry("TDIC", "IBSI", "Major Axis in 3D Length"))); Codes->insert(OFMake_pair(MinorAxisIn3DLength, DSRBasicCodedEntry("P9VJ", "IBSI", "Minor Axis in 3D Length"))); diff --git a/dcmsr/libsrc/CMakeLists.txt b/dcmsr/libsrc/CMakeLists.txt index 73154406..2139fe3a 100644 --- a/dcmsr/libsrc/CMakeLists.txt +++ b/dcmsr/libsrc/CMakeLists.txt @@ -1,5 +1,5 @@ # create library from source files -DCMTK_ADD_LIBRARY(dcmsr dsrcitem dsrcodtn dsrcodvl dsrcomtn dsrcomvl dsrcontn dsrcsidl dsrdattn dsrdncsr dsrdnflt dsrdoc dsrdocst dsrdoctn dsrdoctr dsrdtitn dsrimgfr dsrimgse dsrimgtn dsrimgvl dsritcsr dsrnumtn dsrnumvl dsrpnmtn dsrposcn dsrrefin dsrreftn dsrscogr dsrsc3gr dsrscotn dsrsc3tn dsrscovl dsrsc3vl dsrsoprf dsrstrvl dsrtcodt dsrtcosp dsrtcotn dsrtcoto dsrtcovl dsrtextn dsrtimtn dsrtpltn dsrtree dsrtypes dsruidtn dsrwavch dsrwavtn dsrwavvl dsrxmlc dsrxmld dsriodcc dsrbascc dsrenhcc dsrcomcc dsrkeycc dsrmamcc dsrchecc dsrcolcc dsrprocc dsrxrdcc dsrspecc dsrmaccc dsrimpcc dsrc3dcc dsrrrdcc dsracqcc dsrsaecc dsrprdcc dsrpficc dsrplicc dsrctpl dsrrtpl dsrstpl dsrctxgr) +DCMTK_ADD_LIBRARY(dcmsr dsrcitem dsrcodtn dsrcodvl dsrcomtn dsrcomvl dsrcontn dsrcsidl dsrdattn dsrdncsr dsrdnflt dsrdoc dsrdocst dsrdoctn dsrdoctr dsrdtitn dsrimgfr dsrimgse dsrimgtn dsrimgvl dsritcsr dsrnumtn dsrnumvl dsrpnmtn dsrposcn dsrrefin dsrreftn dsrscogr dsrsc3gr dsrscotn dsrsc3tn dsrscovl dsrsc3vl dsrsoprf dsrstrvl dsrtcodt dsrtcosp dsrtcotn dsrtcoto dsrtcovl dsrtextn dsrtimtn dsrtpltn dsrtree dsrtypes dsruidtn dsrwavch dsrwavtn dsrwavvl dsrxmlc dsrxmld dsriodcc dsrbascc dsrenhcc dsrcomcc dsrkeycc dsrmamcc dsrchecc dsrcolcc dsrprocc dsrxrdcc dsrspecc dsrmaccc dsrimpcc dsrc3dcc dsrrrdcc dsracqcc dsrsaecc dsrprdcc dsrpficc dsrplicc dsrrsdcc dsrctpl dsrrtpl dsrstpl dsrctxgr) DCMTK_TARGET_LINK_MODULES(dcmsr ofstd oflog dcmdata dcmimgle dcmimage) DCMTK_TARGET_LINK_LIBRARIES(dcmsr ${LIBXML_LIBS}) diff --git a/dcmsr/libsrc/Makefile.in b/dcmsr/libsrc/Makefile.in index bc1c80a9..0f30cf98 100644 --- a/dcmsr/libsrc/Makefile.in +++ b/dcmsr/libsrc/Makefile.in @@ -34,7 +34,7 @@ objs = dsrdoc.o dsrposcn.o dsrdncsr.o dsritcsr.o dsrdnflt.o dsrtree.o \ dsriodcc.o dsrbascc.o dsrenhcc.o dsrcomcc.o dsrkeycc.o dsrmamcc.o \ dsrchecc.o dsrcolcc.o dsrprocc.o dsrxrdcc.o dsrspecc.o dsrmaccc.o \ dsrimpcc.o dsrc3dcc.o dsrrrdcc.o dsracqcc.o dsrsaecc.o dsrprdcc.o \ - dsrpficc.o dsrplicc.o + dsrpficc.o dsrplicc.o dsrrsdcc.o library = libdcmsr.$(LIBEXT) diff --git a/dcmsr/libsrc/dsrcodvl.cc b/dcmsr/libsrc/dsrcodvl.cc index f3604e71..c46fc202 100644 --- a/dcmsr/libsrc/dsrcodvl.cc +++ b/dcmsr/libsrc/dsrcodvl.cc @@ -768,12 +768,20 @@ OFCondition DSRCodedEntryValue::checkCode(const OFString &codeValue, { OFCondition result = EC_Normal; /* first, make sure that the mandatory values are non-empty and the type is valid */ - if (codeValue.empty() || (codingSchemeDesignator.empty() && (codeValueType != DSRTypes::CVT_URN)) || codeMeaning.empty()) - result = SR_EC_InvalidValue; + if (codeValueType == DSRTypes::CVT_URN) + { + /* CP-1913: Coding Scheme Version shall not be present if Coding Scheme Designator is absent */ + if (codeValue.empty() || (codingSchemeDesignator.empty() && !codingSchemeVersion.empty()) || codeMeaning.empty()) + result = SR_EC_InvalidValue; + } else if (codeValueType == DSRTypes::CVT_auto) { DCMSR_DEBUG("INTERNAL ERROR: DSRCodedEntryValue::checkCode() called with DSRTypes::CVT_auto"); result = EC_IllegalCall; + } else { + /* short or long code value */ + if (codeValue.empty() || codingSchemeDesignator.empty() || codeMeaning.empty()) + result = SR_EC_InvalidValue; } /* then, check whether the passed values are valid with regards to VR and VM. * tbd: unfortunately, we do not know the character set, so "UNKNOWN" is used. */ diff --git a/dcmsr/libsrc/dsrdoc.cc b/dcmsr/libsrc/dsrdoc.cc index 6ba96ed5..6a70c63a 100644 --- a/dcmsr/libsrc/dsrdoc.cc +++ b/dcmsr/libsrc/dsrdoc.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2019, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -209,6 +209,8 @@ OFCondition DSRDocument::print(STD_NAMESPACE ostream &stream, OFString tmpString, string2; /* update only some DICOM attributes */ updateAttributes(OFFalse /*updateAll*/); + /* check whether general SR modules are used */ + const OFBool usesGeneralSRModules = usesSRDocumentGeneralModule(getDocumentType()); // --- print some general document information --- @@ -300,8 +302,8 @@ OFCondition DSRDocument::print(STD_NAMESPACE ostream &stream, stream << " (" << deviceStr << ")"; DCMSR_PRINT_HEADER_FIELD_END } - /* Key Object Selection Documents do not contain the SR Document General Module */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesGeneralSRModules) { /* preliminary flag */ if (!PreliminaryFlag.isEmpty()) @@ -342,7 +344,7 @@ OFCondition DSRDocument::print(STD_NAMESPACE ostream &stream, stream << ReferencedInstances.getNumberOfItems(); DCMSR_PRINT_HEADER_FIELD_END } - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesGeneralSRModules) { /* verification flag */ DCMSR_PRINT_HEADER_FIELD_START("Verification Flag ", " : ") @@ -421,7 +423,7 @@ OFCondition DSRDocument::checkDatasetForReading(DcmItem &dataset, /* check modality */ if (result.good()) { - if (documentType == DT_KeyObjectSelectionDocument) + if (usesKeyObjectDocumentSeriesModule(documentType)) result = getAndCheckElementFromDataset(dataset, modality, "1", "1", "KeyObjectDocumentSeriesModule"); else result = getAndCheckElementFromDataset(dataset, modality, "1", "1", "SRDocumentSeriesModule"); @@ -508,7 +510,7 @@ OFCondition DSRDocument::read(DcmItem &dataset, // --- SR Document Series Module / Key Object Document Series Module --- getElementFromDataset(dataset, Modality); /* already checked */ - if (documentType == DT_KeyObjectSelectionDocument) + if (usesKeyObjectDocumentSeriesModule(documentType)) { getAndCheckElementFromDataset(dataset, SeriesInstanceUID, "1", "1", "KeyObjectDocumentSeriesModule"); getAndCheckElementFromDataset(dataset, SeriesNumber, "1", "1", "KeyObjectDocumentSeriesModule"); @@ -535,7 +537,7 @@ OFCondition DSRDocument::read(DcmItem &dataset, removeAttributeFromSequence(ReferencedPerformedProcedureStep, DCM_DigitalSignaturesSequence); // --- SR Document General Module / Key Object Document Module --- - if (documentType == DT_KeyObjectSelectionDocument) + if (usesKeyObjectDocumentModule(documentType)) { getAndCheckElementFromDataset(dataset, InstanceNumber, "1", "1", "KeyObjectDocumentModule"); getAndCheckElementFromDataset(dataset, ContentDate, "1", "1", "KeyObjectDocumentModule"); @@ -566,8 +568,8 @@ OFCondition DSRDocument::read(DcmItem &dataset, /* update internal enumerated values and perform additional checks */ - /* Key Object Selection Documents do not contain the SR Document General Module */ - if (documentType != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(documentType)) { /* get and check PreliminaryFlag (if present) */ if (!PreliminaryFlag.isEmpty()) @@ -580,7 +582,7 @@ OFCondition DSRDocument::read(DcmItem &dataset, CompletionFlagEnum = enumeratedValueToCompletionFlag(getStringValueFromElement(CompletionFlag, tmpString)); if (CompletionFlagEnum == CF_invalid) printUnknownValueWarningMessage("CompletionFlag", tmpString.c_str()); - else if ((CompletionFlagEnum == CF_Partial) && (documentType == DT_XRayRadiationDoseSR)) + else if ((documentType == DT_XRayRadiationDoseSR) && (CompletionFlagEnum != CF_Complete)) DCMSR_WARN("Invalid value for Completion Flag, should be 'COMPLETE' for X-Ray Radiation Dose SR"); /* get and check VerificationFlag / VerifyingObserverSequence */ VerificationFlagEnum = enumeratedValueToVerificationFlag(getStringValueFromElement(VerificationFlag, tmpString)); @@ -645,7 +647,7 @@ OFCondition DSRDocument::write(DcmItem &dataset, updateAttributes(); /* checking particular values */ - if ((CompletionFlagEnum == CF_Partial) && (getDocumentType() == DT_XRayRadiationDoseSR)) + if ((getDocumentType() == DT_XRayRadiationDoseSR) && (CompletionFlagEnum != CF_Complete)) DCMSR_WARN("Invalid value for Completion Flag, should be 'COMPLETE' for X-Ray Radiation Dose SR"); /* write general document attributes */ @@ -710,7 +712,7 @@ OFCondition DSRDocument::write(DcmItem &dataset, } // --- SR Document Series Module / Key Object Document Series Module --- - if (getDocumentType() == DT_KeyObjectSelectionDocument) + if (usesKeyObjectDocumentSeriesModule(getDocumentType())) { addElementToDataset(result, dataset, new DcmCodeString(Modality), "1", "1", "KeyObjectDocumentSeriesModule"); addElementToDataset(result, dataset, new DcmUniqueIdentifier(SeriesInstanceUID), "1", "1", "KeyObjectDocumentSeriesModule"); @@ -736,7 +738,7 @@ OFCondition DSRDocument::write(DcmItem &dataset, } // --- SR Document General Module / Key Object Document Module --- - if (getDocumentType() == DT_KeyObjectSelectionDocument) + if (usesKeyObjectDocumentModule(getDocumentType())) { addElementToDataset(result, dataset, new DcmIntegerString(InstanceNumber), "1", "1", "KeyObjectDocumentModule"); addElementToDataset(result, dataset, new DcmDate(ContentDate), "1", "1", "KeyObjectDocumentModule"); @@ -911,7 +913,7 @@ OFCondition DSRDocument::readXMLDocumentHeader(DSRXMLDocument &doc, result = CurrentRequestedProcedureEvidence.readXML(doc, cursor.getChild(), flags); else if (typeString == "Pertinent Other") { - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesSRDocumentGeneralModule(getDocumentType())) result = PertinentOtherEvidence.readXML(doc, cursor.getChild(), flags); else doc.printUnexpectedNodeWarning(cursor); @@ -1131,21 +1133,22 @@ OFCondition DSRDocument::readXMLDocumentData(const DSRXMLDocument &doc, if (cursor.valid()) { OFString tmpString; - const E_DocumentType documentType = getDocumentType(); + /* check whether general SR modules are used */ + const OFBool usesGeneralSRModules = usesSRDocumentGeneralModule(getDocumentType()); result = EC_Normal; /* iterate over all nodes */ while (cursor.valid() && result.good()) { /* check for known element tags - (Key Object Selection Documents do not contain the SR Document General Module) */ - if ((documentType != DT_KeyObjectSelectionDocument) && doc.matchNode(cursor, "preliminary")) + (not all SR IODs contain the SR Document General Module) */ + if (usesGeneralSRModules && doc.matchNode(cursor, "preliminary")) { /* Preliminary Flag */ PreliminaryFlagEnum = enumeratedValueToPreliminaryFlag(doc.getStringFromAttribute(cursor, tmpString, "flag")); if (PreliminaryFlagEnum == PF_invalid) printUnknownValueWarningMessage("PreliminaryFlag", tmpString.c_str()); } - else if ((documentType != DT_KeyObjectSelectionDocument) && doc.matchNode(cursor, "completion")) + else if (usesGeneralSRModules && doc.matchNode(cursor, "completion")) { /* Completion Flag */ CompletionFlagEnum = enumeratedValueToCompletionFlag(doc.getStringFromAttribute(cursor, tmpString, "flag")); @@ -1158,7 +1161,7 @@ OFCondition DSRDocument::readXMLDocumentData(const DSRXMLDocument &doc, } else printUnknownValueWarningMessage("CompletionFlag", tmpString.c_str()); } - else if ((documentType != DT_KeyObjectSelectionDocument) && doc.matchNode(cursor, "verification")) + else if (usesGeneralSRModules && doc.matchNode(cursor, "verification")) { /* Verification Flag */ VerificationFlagEnum = enumeratedValueToVerificationFlag(doc.getStringFromAttribute(cursor, tmpString, "flag")); @@ -1172,7 +1175,7 @@ OFCondition DSRDocument::readXMLDocumentData(const DSRXMLDocument &doc, } else printUnknownValueWarningMessage("VerificationFlag", tmpString.c_str()); } - else if ((documentType != DT_KeyObjectSelectionDocument) && doc.matchNode(cursor, "predecessor")) + else if (usesGeneralSRModules && doc.matchNode(cursor, "predecessor")) { /* Predecessor Documents Sequence (optional) */ result = PredecessorDocuments.readXML(doc, cursor.getChild(), flags); @@ -1280,6 +1283,8 @@ OFCondition DSRDocument::writeXML(STD_NAMESPACE ostream &stream, OFString tmpString; /* update all DICOM attributes */ updateAttributes(); + /* check whether general SR modules are used */ + const OFBool usesGeneralSRModules = usesSRDocumentGeneralModule(getDocumentType()); // --- XML document structure (start) --- @@ -1414,7 +1419,7 @@ OFCondition DSRDocument::writeXML(STD_NAMESPACE ostream &stream, CurrentRequestedProcedureEvidence.writeXML(stream, flags); stream << "" << OFendl; } - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesGeneralSRModules) { if ((flags & XF_writeEmptyTags) || !PertinentOtherEvidence.isEmpty()) { @@ -1431,7 +1436,7 @@ OFCondition DSRDocument::writeXML(STD_NAMESPACE ostream &stream, } stream << "" << OFendl; - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesGeneralSRModules) { if (!PreliminaryFlag.isEmpty()) stream << "" << OFendl; @@ -1648,6 +1653,8 @@ OFCondition DSRDocument::renderHTML(STD_NAMESPACE ostream &stream, OFString htmlString; /* update only some DICOM attributes */ updateAttributes(OFFalse /*updateAll*/); + /* check whether general SR modules are used */ + const OFBool usesGeneralSRModules = usesSRDocumentGeneralModule(getDocumentType()); // --- HTML/XHTML document structure (start) --- @@ -1821,7 +1828,7 @@ OFCondition DSRDocument::renderHTML(STD_NAMESPACE ostream &stream, stream << "" << OFendl; stream << "" << OFendl; } - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesGeneralSRModules) { /* preliminary flag */ if (!PreliminaryFlag.isEmpty()) @@ -1870,7 +1877,7 @@ OFCondition DSRDocument::renderHTML(STD_NAMESPACE ostream &stream, renderHTMLReferenceList(stream, ReferencedInstances, flags); stream << "" << OFendl; } - if (getDocumentType() != DT_KeyObjectSelectionDocument) + if (usesGeneralSRModules) { /* verification flag */ stream << "" << OFendl; @@ -2063,8 +2070,8 @@ DSRTypes::E_PreliminaryFlag DSRDocument::getPreliminaryFlag() const OFCondition DSRDocument::setPreliminaryFlag(const E_PreliminaryFlag flag) { OFCondition result = EC_IllegalCall; - /* not applicable to Key Object Selection Documents */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(getDocumentType())) { PreliminaryFlagEnum = flag; result = EC_Normal; @@ -2476,8 +2483,8 @@ OFCondition DSRDocument::setCompletionFlagDescription(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; - /* not applicable to Key Object Selection Documents */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(getDocumentType())) { if (check) result = DcmLongString::checkStringValue(value, "1", getSpecificCharacterSet()); @@ -2855,8 +2862,8 @@ OFCondition DSRDocument::changeDocumentType(const E_DocumentType documentType) OFCondition DSRDocument::createRevisedVersion(const OFBool clearList) { OFCondition result = EC_IllegalCall; - /* not applicable to Key Object Selection Documents */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(getDocumentType())) { /* check whether document is already completed */ if (CompletionFlagEnum == CF_Complete) @@ -2902,8 +2909,8 @@ OFCondition DSRDocument::completeDocument(const OFString &description, const OFBool check) { OFCondition result = EC_IllegalCall; - /* not applicable to Key Object Selection Documents */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(getDocumentType())) { /* if document is not already completed */ if (CompletionFlagEnum != CF_Complete) @@ -2940,8 +2947,8 @@ OFCondition DSRDocument::verifyDocument(const OFString &observerName, const OFBool check) { OFCondition result = EC_IllegalCall; - /* not applicable to Key Object Selection Documents */ - if (getDocumentType() != DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(getDocumentType())) { /* verify completed documents only */ if (CompletionFlagEnum == CF_Complete) @@ -3087,18 +3094,9 @@ void DSRDocument::updateAttributes(const OFBool updateAll, if (ContentTime.isEmpty()) ContentTime.putString(getStringValueFromElement(InstanceCreationTime)); } - if (documentType == DT_KeyObjectSelectionDocument) + /* not all SR IODs contain the SR Document General Module */ + if (usesSRDocumentGeneralModule(documentType)) { - /* these flags are not used for Key Object Selection Documents */ - PreliminaryFlagEnum = PF_invalid; - CompletionFlagEnum = CF_invalid; - VerificationFlagEnum = VF_invalid; - PreliminaryFlag.clear(); - CompletionFlag.clear(); - CompletionFlagDescription.clear(); - VerificationFlag.clear(); - VerifyingObserver.clear(); - } else { /* set preliminary flag */ PreliminaryFlag.putString(preliminaryFlagToEnumeratedValue(PreliminaryFlagEnum)); /* check and adjust completion flag if required */ @@ -3109,5 +3107,15 @@ void DSRDocument::updateAttributes(const OFBool updateAll, if (VerificationFlagEnum == VF_invalid) VerificationFlagEnum = VF_Unverified; VerificationFlag.putString(verificationFlagToEnumeratedValue(VerificationFlagEnum)); + } else { + /* if not, reset the various flags and clear related information */ + PreliminaryFlagEnum = PF_invalid; + CompletionFlagEnum = CF_invalid; + VerificationFlagEnum = VF_invalid; + PreliminaryFlag.clear(); + CompletionFlag.clear(); + CompletionFlagDescription.clear(); + VerificationFlag.clear(); + VerifyingObserver.clear(); } } diff --git a/dcmsr/libsrc/dsrimgvl.cc b/dcmsr/libsrc/dsrimgvl.cc index a15a7fa1..8e50acf5 100644 --- a/dcmsr/libsrc/dsrimgvl.cc +++ b/dcmsr/libsrc/dsrimgvl.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2018, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -688,7 +688,7 @@ OFBool DSRImageReferenceValue::appliesToSegment(const Uint16 segmentNumber) cons OFBool DSRImageReferenceValue::isSegmentationObject(const OFString &sopClassUID) const { - /* check for all segmentation SOP classes (according to DICOM PS 3.6-2017e) */ + /* check for all segmentation SOP classes (according to DICOM PS 3.6-2020c) */ return (sopClassUID == UID_SegmentationStorage) || (sopClassUID == UID_SurfaceSegmentationStorage); } diff --git a/dcmsr/libsrc/dsrpficc.cc b/dcmsr/libsrc/dsrpficc.cc index b8c142a6..46859391 100644 --- a/dcmsr/libsrc/dsrpficc.cc +++ b/dcmsr/libsrc/dsrpficc.cc @@ -77,27 +77,27 @@ OFBool DSRPerformedImagingAgentAdministrationSRConstraintChecker::checkContentRe /* row 1 of the table */ if ((relationshipType == RT_contains) && (sourceValueType == VT_Container)) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Composite) || - (targetValueType == VT_Image) || (targetValueType == VT_Waveform) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Composite) || (targetValueType == VT_Image) || + (targetValueType == VT_Waveform) || (targetValueType == VT_Container); } /* row 2 of the table */ else if ((relationshipType == RT_hasObsContext) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num) || (sourceValueType == VT_Container))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Composite); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Composite); } /* row 3 of the table */ else if ((relationshipType == RT_hasAcqContext) && ((sourceValueType == VT_Container) || (sourceValueType == VT_Image) || (sourceValueType == VT_Waveform) || (sourceValueType == VT_Composite) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Container); } /* row 4 of the table */ else if (relationshipType == RT_hasConceptMod) @@ -108,26 +108,25 @@ OFBool DSRPerformedImagingAgentAdministrationSRConstraintChecker::checkContentRe else if ((relationshipType == RT_hasProperties) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Image) || - (targetValueType == VT_Waveform) || (targetValueType == VT_Composite) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Image) ||(targetValueType == VT_Waveform) || + (targetValueType == VT_Composite) || (targetValueType == VT_Container); } /* row 6 of the table */ else if ((relationshipType == RT_hasProperties) && (sourceValueType == VT_PName)) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_DateTime) || - (targetValueType == VT_Date) || (targetValueType == VT_Time) || (targetValueType == VT_UIDRef) || - (targetValueType == VT_PName); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_DateTime) || + (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) ||(targetValueType == VT_PName); } /* row 7 of the table */ else if ((relationshipType == RT_inferredFrom) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Image) || - (targetValueType == VT_Waveform) || (targetValueType == VT_Composite) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Image) || (targetValueType == VT_Waveform) || + (targetValueType == VT_Composite) || (targetValueType == VT_Container); } } return result; diff --git a/dcmsr/libsrc/dsrplicc.cc b/dcmsr/libsrc/dsrplicc.cc index e9c4218f..ad1de2fc 100644 --- a/dcmsr/libsrc/dsrplicc.cc +++ b/dcmsr/libsrc/dsrplicc.cc @@ -77,25 +77,25 @@ OFBool DSRPlannedImagingAgentAdministrationSRConstraintChecker::checkContentRela /* row 1 of the table */ if ((relationshipType == RT_contains) && (sourceValueType == VT_Container)) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Container); } /* row 2 of the table */ else if ((relationshipType == RT_hasObsContext) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num) || (sourceValueType == VT_Container))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName); } /* row 3 of the table */ else if ((relationshipType == RT_hasAcqContext) && ((sourceValueType == VT_Container) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Container); } /* row 4 of the table */ else if (relationshipType == RT_hasConceptMod) @@ -106,24 +106,23 @@ OFBool DSRPlannedImagingAgentAdministrationSRConstraintChecker::checkContentRela else if ((relationshipType == RT_hasProperties) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Container); } /* row 6 of the table */ else if ((relationshipType == RT_hasProperties) && (sourceValueType == VT_PName)) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_DateTime) || - (targetValueType == VT_Date) || (targetValueType == VT_Time) || (targetValueType == VT_UIDRef) || - (targetValueType == VT_PName); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_DateTime) || + (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) ||(targetValueType == VT_PName); } /* row 7 of the table */ else if ((relationshipType == RT_inferredFrom) && ((sourceValueType == VT_Text) || (sourceValueType == VT_Code) || (sourceValueType == VT_Num))) { - result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || - (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_Time) || - (targetValueType == VT_UIDRef) || (targetValueType == VT_PName) || (targetValueType == VT_Container); + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || (targetValueType == VT_Num) || + (targetValueType == VT_DateTime) || (targetValueType == VT_Date) || (targetValueType == VT_UIDRef) || + (targetValueType == VT_PName) || (targetValueType == VT_Container); } } return result; diff --git a/dcmsr/libsrc/dsrrsdcc.cc b/dcmsr/libsrc/dsrrsdcc.cc new file mode 100644 index 00000000..b0725620 --- /dev/null +++ b/dcmsr/libsrc/dsrrsdcc.cc @@ -0,0 +1,96 @@ +/* + * + * Copyright (C) 2020, J. Riesmeier, Oldenburg, Germany + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmsr + * + * Author: Joerg Riesmeier + * + * Purpose: + * classes: DSRRenditionSelectionDocumentConstraintChecker + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmsr/dsrrsdcc.h" + + +DSRRenditionSelectionDocumentConstraintChecker::DSRRenditionSelectionDocumentConstraintChecker() + : DSRIODConstraintChecker() +{ +} + + +DSRRenditionSelectionDocumentConstraintChecker::~DSRRenditionSelectionDocumentConstraintChecker() +{ +} + + +OFBool DSRRenditionSelectionDocumentConstraintChecker::isByReferenceAllowed() const +{ + return OFFalse; +} + + +OFBool DSRRenditionSelectionDocumentConstraintChecker::isTemplateSupportRequired() const +{ + return OFTrue; +} + + +OFCondition DSRRenditionSelectionDocumentConstraintChecker::getRootTemplateIdentification(OFString &templateIdentifier, + OFString &mappingResource) const +{ + templateIdentifier = "2010"; + mappingResource = "DCMR"; + return EC_Normal; +} + + +DSRTypes::E_DocumentType DSRRenditionSelectionDocumentConstraintChecker::getDocumentType() const +{ + return DT_RenditionSelectionDocument; +} + + +OFBool DSRRenditionSelectionDocumentConstraintChecker::checkContentRelationship(const E_ValueType sourceValueType, + const E_RelationshipType relationshipType, + const E_ValueType targetValueType, + const OFBool byReference) const +{ + /* the following code implements the constraints of table A.35.21-2 in DICOM PS3.3 */ + OFBool result = OFFalse; + /* by-reference relationships not allowed at all */ + if (!byReference) + { + /* row 1 of the table */ + if ((relationshipType == RT_contains) && (sourceValueType == VT_Container)) + { + result = (targetValueType == VT_Text) || (targetValueType == VT_Image) || + (targetValueType == VT_Waveform) || (targetValueType == VT_Composite); + } + /* row 2 of the table */ + else if ((relationshipType == RT_hasObsContext) && (sourceValueType == VT_Container)) + { + result = (targetValueType == VT_Text) || (targetValueType == VT_Code) || + (targetValueType == VT_UIDRef) || (targetValueType == VT_PName); + } + /* row 3 of the table */ + else if ((relationshipType == RT_hasConceptMod) && (sourceValueType == VT_Container)) + { + result = (targetValueType == VT_Code); + } + } + return result; +} diff --git a/dcmsr/libsrc/dsrtypes.cc b/dcmsr/libsrc/dsrtypes.cc index e2d7facb..b0b8cd5e 100644 --- a/dcmsr/libsrc/dsrtypes.cc +++ b/dcmsr/libsrc/dsrtypes.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2019, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -59,6 +59,7 @@ #include "dcmtk/dcmsr/dsrprdcc.h" #include "dcmtk/dcmsr/dsrpficc.h" #include "dcmtk/dcmsr/dsrplicc.h" +#include "dcmtk/dcmsr/dsrrsdcc.h" #include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcvrda.h" @@ -320,30 +321,32 @@ makeOFConditionConst(SR_EC_CannotProcessIncludedTemplates, OFM_dcmsr, 34, O const size_t EM_EnhancedEquipment = 1 << 0; const size_t EM_Timezone = 1 << 1; const size_t EM_Synchronization = 1 << 2; +const size_t EM_KeyObjectDocument = 1 << 3; static const S_DocumentTypeNameMap DocumentTypeNameMap[] = { - {DSRTypes::DT_invalid, "", 0, "", "invalid document type"}, - {DSRTypes::DT_BasicTextSR, UID_BasicTextSRStorage, 0, "SR", "Basic Text SR"}, - {DSRTypes::DT_EnhancedSR, UID_EnhancedSRStorage, 0, "SR", "Enhanced SR"}, - {DSRTypes::DT_ComprehensiveSR, UID_ComprehensiveSRStorage, 0, "SR", "Comprehensive SR"}, - {DSRTypes::DT_KeyObjectSelectionDocument, UID_KeyObjectSelectionDocumentStorage, 0, "KO", "Key Object Selection Document"}, - {DSRTypes::DT_MammographyCadSR, UID_MammographyCADSRStorage, 0, "SR", "Mammography CAD SR"}, - {DSRTypes::DT_ChestCadSR, UID_ChestCADSRStorage, 0, "SR", "Chest CAD SR"}, - {DSRTypes::DT_ColonCadSR, UID_ColonCADSRStorage, EM_EnhancedEquipment, "SR", "Colon CAD SR"}, - {DSRTypes::DT_ProcedureLog, UID_ProcedureLogStorage, EM_Synchronization, "SR", "Procedure Log"}, - {DSRTypes::DT_XRayRadiationDoseSR, UID_XRayRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "X-Ray Radiation Dose SR"}, - {DSRTypes::DT_SpectaclePrescriptionReport, UID_SpectaclePrescriptionReportStorage, EM_EnhancedEquipment, "SR", "Spectacle Prescription Report"}, - {DSRTypes::DT_MacularGridThicknessAndVolumeReport, UID_MacularGridThicknessAndVolumeReportStorage, EM_EnhancedEquipment, "SR", "Macular Grid Thickness and Volume Report"}, - {DSRTypes::DT_ImplantationPlanSRDocument, UID_ImplantationPlanSRDocumentStorage, EM_EnhancedEquipment, "SR", "Implantation Plan SR Document"}, - {DSRTypes::DT_Comprehensive3DSR, UID_Comprehensive3DSRStorage, 0, "SR", "Comprehensive 3D SR"}, - {DSRTypes::DT_RadiopharmaceuticalRadiationDoseSR, UID_RadiopharmaceuticalRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "Radiopharmaceutical Radiation Dose SR"}, - {DSRTypes::DT_ExtensibleSR, UID_ExtensibleSRStorage, EM_EnhancedEquipment, "SR", "Extensible SR"}, - {DSRTypes::DT_AcquisitionContextSR, UID_AcquisitionContextSRStorage, EM_EnhancedEquipment, "SR", "Acquisition Context SR"}, - {DSRTypes::DT_SimplifiedAdultEchoSR, UID_SimplifiedAdultEchoSRStorage, EM_EnhancedEquipment | EM_Timezone, "SR", "Simplified Adult Echo SR"}, - {DSRTypes::DT_PatientRadiationDoseSR, UID_PatientRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "Patient Radiation Dose SR"}, - {DSRTypes::DT_PerformedImagingAgentAdministrationSR, UID_PerformedImagingAgentAdministrationSRStorage, EM_EnhancedEquipment | EM_Synchronization, "SR", "Performed Imaging Agent Administration SR"}, - {DSRTypes::DT_PlannedImagingAgentAdministrationSR, UID_PlannedImagingAgentAdministrationSRStorage, EM_EnhancedEquipment, "SR", "Planned Imaging Agent Administration SR"} + {DSRTypes::DT_invalid, "", 0, "", "invalid document type"}, + {DSRTypes::DT_BasicTextSR, UID_BasicTextSRStorage, 0, "SR", "Basic Text SR"}, + {DSRTypes::DT_EnhancedSR, UID_EnhancedSRStorage, 0, "SR", "Enhanced SR"}, + {DSRTypes::DT_ComprehensiveSR, UID_ComprehensiveSRStorage, 0, "SR", "Comprehensive SR"}, + {DSRTypes::DT_KeyObjectSelectionDocument, UID_KeyObjectSelectionDocumentStorage, EM_KeyObjectDocument, "KO", "Key Object Selection Document"}, + {DSRTypes::DT_MammographyCadSR, UID_MammographyCADSRStorage, 0, "SR", "Mammography CAD SR"}, + {DSRTypes::DT_ChestCadSR, UID_ChestCADSRStorage, 0, "SR", "Chest CAD SR"}, + {DSRTypes::DT_ColonCadSR, UID_ColonCADSRStorage, EM_EnhancedEquipment, "SR", "Colon CAD SR"}, + {DSRTypes::DT_ProcedureLog, UID_ProcedureLogStorage, EM_Synchronization, "SR", "Procedure Log"}, + {DSRTypes::DT_XRayRadiationDoseSR, UID_XRayRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "X-Ray Radiation Dose SR"}, + {DSRTypes::DT_SpectaclePrescriptionReport, UID_SpectaclePrescriptionReportStorage, EM_EnhancedEquipment, "SR", "Spectacle Prescription Report"}, + {DSRTypes::DT_MacularGridThicknessAndVolumeReport, UID_MacularGridThicknessAndVolumeReportStorage, EM_EnhancedEquipment, "SR", "Macular Grid Thickness and Volume Report"}, + {DSRTypes::DT_ImplantationPlanSRDocument, UID_ImplantationPlanSRDocumentStorage, EM_EnhancedEquipment, "SR", "Implantation Plan SR Document"}, + {DSRTypes::DT_Comprehensive3DSR, UID_Comprehensive3DSRStorage, 0, "SR", "Comprehensive 3D SR"}, + {DSRTypes::DT_RadiopharmaceuticalRadiationDoseSR, UID_RadiopharmaceuticalRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "Radiopharmaceutical Radiation Dose SR"}, + {DSRTypes::DT_ExtensibleSR, UID_ExtensibleSRStorage, EM_EnhancedEquipment, "SR", "Extensible SR"}, + {DSRTypes::DT_AcquisitionContextSR, UID_AcquisitionContextSRStorage, EM_EnhancedEquipment, "SR", "Acquisition Context SR"}, + {DSRTypes::DT_SimplifiedAdultEchoSR, UID_SimplifiedAdultEchoSRStorage, EM_EnhancedEquipment | EM_Timezone, "SR", "Simplified Adult Echo SR"}, + {DSRTypes::DT_PatientRadiationDoseSR, UID_PatientRadiationDoseSRStorage, EM_EnhancedEquipment, "SR", "Patient Radiation Dose SR"}, + {DSRTypes::DT_PerformedImagingAgentAdministrationSR, UID_PerformedImagingAgentAdministrationSRStorage, EM_EnhancedEquipment | EM_Synchronization, "SR", "Performed Imaging Agent Administration SR"}, + {DSRTypes::DT_PlannedImagingAgentAdministrationSR, UID_PlannedImagingAgentAdministrationSRStorage, EM_EnhancedEquipment, "SR", "Planned Imaging Agent Administration SR"}, + {DSRTypes::DT_RenditionSelectionDocument, UID_RenditionSelectionDocumentRealTimeCommunication, EM_EnhancedEquipment | EM_Synchronization | EM_KeyObjectDocument, "KO", "Rendition Selection Document"} }; @@ -584,6 +587,36 @@ OFBool DSRTypes::requiresSynchronizationModule(const E_DocumentType documentType } +OFBool DSRTypes::usesSRDocumentSeriesModule(const E_DocumentType documentType) +{ + /* SR Document Series Module and Key Object Document Series Module are mutually exclusive */ + return !usesKeyObjectDocumentSeriesModule(documentType); +} + + +OFBool DSRTypes::usesKeyObjectDocumentSeriesModule(const E_DocumentType documentType) +{ + /* Key Object Document Series Module is used if (and only if) Key Object Document Module is used */ + return usesKeyObjectDocumentModule(documentType); +} + + +OFBool DSRTypes::usesSRDocumentGeneralModule(const E_DocumentType documentType) +{ + /* SR Document Module and Key Object Document Module are mutually exclusive */ + return !usesKeyObjectDocumentModule(documentType); +} + + +OFBool DSRTypes::usesKeyObjectDocumentModule(const E_DocumentType documentType) +{ + const S_DocumentTypeNameMap *iterator = DocumentTypeNameMap; + while ((iterator->Type != DT_last) && (iterator->Type != documentType)) + iterator++; + return (iterator->ExtendedModules & EM_KeyObjectDocument) > 0; +} + + const char *DSRTypes::relationshipTypeToDefinedTerm(const E_RelationshipType relationshipType) { const S_RelationshipTypeNameMap *iterator = RelationshipTypeNameMap; @@ -1519,6 +1552,9 @@ DSRIODConstraintChecker *DSRTypes::createIODConstraintChecker(const E_DocumentTy case DT_PlannedImagingAgentAdministrationSR: checker = new DSRPlannedImagingAgentAdministrationSRConstraintChecker(); break; + case DT_RenditionSelectionDocument: + checker = new DSRRenditionSelectionDocumentConstraintChecker(); + break; case DT_invalid: /* nothing to do */ break; diff --git a/dcmsr/libsrc/dsrwavvl.cc b/dcmsr/libsrc/dsrwavvl.cc index 949da637..3b0613a2 100644 --- a/dcmsr/libsrc/dsrwavvl.cc +++ b/dcmsr/libsrc/dsrwavvl.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2019, OFFIS e.V. + * Copyright (C) 2000-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -261,7 +261,7 @@ OFCondition DSRWaveformReferenceValue::checkSOPClassUID(const OFString &sopClass OFCondition result = DSRCompositeReferenceValue::checkSOPClassUID(sopClassUID); if (result.good()) { - /* check for all valid/known SOP classes (according to DICOM PS 3.6-2017e) */ + /* check for all valid/known SOP classes (according to DICOM PS 3.6-2020c) */ if ((sopClassUID != UID_TwelveLeadECGWaveformStorage) && (sopClassUID != UID_GeneralECGWaveformStorage) && (sopClassUID != UID_AmbulatoryECGWaveformStorage) && @@ -270,7 +270,13 @@ OFCondition DSRWaveformReferenceValue::checkSOPClassUID(const OFString &sopClass (sopClassUID != UID_BasicVoiceAudioWaveformStorage) && (sopClassUID != UID_GeneralAudioWaveformStorage) && (sopClassUID != UID_ArterialPulseWaveformStorage) && - (sopClassUID != UID_RespiratoryWaveformStorage)) + (sopClassUID != UID_RespiratoryWaveformStorage) && + (sopClassUID != UID_MultichannelRespiratoryWaveformStorage) && + (sopClassUID != UID_RoutineScalpElectroencephalogramWaveformStorage) && + (sopClassUID != UID_ElectromyogramWaveformStorage) && + (sopClassUID != UID_ElectrooculogramWaveformStorage) && + (sopClassUID != UID_SleepElectroencephalogramWaveformStorage) && + (sopClassUID != UID_BodyPositionWaveformStorage)) { result = SR_EC_InvalidValue; } diff --git a/dcmsr/tests/tsrcmr.cc b/dcmsr/tests/tsrcmr.cc index c0ec0821..8fba9f5c 100644 --- a/dcmsr/tests/tsrcmr.cc +++ b/dcmsr/tests/tsrcmr.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -27,6 +27,7 @@ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcdict.h" #include "dcmtk/dcmsr/dsrdoc.h" #include "dcmtk/dcmsr/dsrnumvl.h" @@ -273,6 +274,13 @@ OFTEST(dcmsr_TID1411_VolumetricROIMeasurements) OFTEST(dcmsr_TID1500_MeasurementReport) { + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + TID1500_MeasurementReport report(CMR_CID7021::ImagingMeasurementReport); DSRCodedEntryValue title; /* check initial settings */ @@ -486,6 +494,13 @@ OFTEST(dcmsr_TID1501_MeasurementGroup) OFTEST(dcmsr_TID1600_ImageLibrary) { + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + TID1600_ImageLibrary library; DcmItem *item1, *item2; /* check template identification */ diff --git a/dcmsr/tests/tsrcodvl.cc b/dcmsr/tests/tsrcodvl.cc index 1155d8e2..0a0e534a 100644 --- a/dcmsr/tests/tsrcodvl.cc +++ b/dcmsr/tests/tsrcodvl.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2015-2019, J. Riesmeier, Oldenburg, Germany + * Copyright (C) 2015-2020, J. Riesmeier, Oldenburg, Germany * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -27,6 +27,7 @@ #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcdict.h" #include "dcmtk/dcmsr/dsrcodvl.h" @@ -39,6 +40,7 @@ OFTEST(dcmsr_validCompleteOrEmptyCode) const DSRCodedEntryValue code3("a little too long\\with VM>1", "99TEST", "some invalid test code", DSRTypes::CVT_Short, OFFalse /*check*/); const DSRCodedEntryValue code4("", "", ""); const DSRCodedEntryValue code5("urn:0817", "" /* empty coding scheme designator */, "some other code"); + const DSRCodedEntryValue code6("urn:0817", "" /* empty coding scheme designator */, "1.0" /* non-empty coding scheme version */, "some other code", DSRTypes::CVT_URN, OFFalse /*check*/); /* then, perform some tests with these codes */ OFCHECK(code1.isValid()); OFCHECK(code1.isComplete()); @@ -55,6 +57,9 @@ OFTEST(dcmsr_validCompleteOrEmptyCode) OFCHECK(code5.isValid()); OFCHECK(code5.isComplete()); OFCHECK(!code5.isEmpty()); + OFCHECK(!code6.isValid()); + OFCHECK(code6.isComplete()); + OFCHECK(!code6.isEmpty()); } @@ -99,6 +104,13 @@ OFTEST(dcmsr_determineCodeValueType) OFTEST(dcmsr_writeCodeSequence) { + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + DcmDataset dataset; /* first, try the standard case (short code value) */ DSRCodedEntryValue codedEntry("121206", "DCM", "Distance", DSRTypes::CVT_Short); diff --git a/dcmtls/CMakeLists.txt b/dcmtls/CMakeLists.txt index d40200d5..d3248235 100644 --- a/dcmtls/CMakeLists.txt +++ b/dcmtls/CMakeLists.txt @@ -5,6 +5,6 @@ project(dcmtls) include_directories("${dcmtls_SOURCE_DIR}/include" "${ofstd_SOURCE_DIR}/include" "${oflog_SOURCE_DIR}/include" "${dcmdata_SOURCE_DIR}/include" "${dcmnet_SOURCE_DIR}/include" ${ZLIB_INCDIR} ${OPENSSL_INCDIR}) # recurse into subdirectories -foreach(SUBDIR libsrc include docs) +foreach(SUBDIR libsrc include docs tests) add_subdirectory(${SUBDIR}) endforeach() diff --git a/dcmtls/docs/certstor.txt b/dcmtls/docs/certstor.txt index c1d3d15d..e20de23a 100644 --- a/dcmtls/docs/certstor.txt +++ b/dcmtls/docs/certstor.txt @@ -1,6 +1,6 @@ -============================================================================= +============================================================ CERTIFICATION AUTHORITY (CA) CERTIFICATE MANAGEMENT IN DCMTK -============================================================================= +============================================================ All tools in DCMTK that support TLS encrypted network connections need to have a list of trusted certificates (typically CA certificates) @@ -12,10 +12,11 @@ file-based and directory-based. The command line tools in DCMTK offer the following command line options for this purpose: certification authority: - +cf --add-cert-file [c]ertificate filename: string - add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string - add certificates in d to list of certificates + +cf --add-cert-file [f]ilename: string + add certificate file to list of certificates + + +cd --add-cert-dir [d]irectory: string + add certificates in d to list of certificates When using DCMTK at library level, the methods corresponding to these command line options are DcmTransportLayer::addTrustedCertificateFile() diff --git a/dcmtls/docs/dcmtls.dox b/dcmtls/docs/dcmtls.dox index c99cc2d7..ee6dffdd 100644 --- a/dcmtls/docs/dcmtls.dox +++ b/dcmtls/docs/dcmtls.dox @@ -14,6 +14,7 @@ The main interface classes are: \section Files The following files provide further documentation: +\li \ref file_certstor \li \ref file_ciphers \li \ref file_randseed @@ -59,6 +60,11 @@ ASC_setTransportLayerType(params, 1); */ +/*! + \page file_certstor certstor.txt file + \verbinclude certstor.txt +*/ + /*! \page file_ciphers ciphers.txt file \verbinclude ciphers.txt diff --git a/dcmtls/libsrc/Makefile.dep b/dcmtls/libsrc/Makefile.dep index 153be7d1..3788d465 100644 --- a/dcmtls/libsrc/Makefile.dep +++ b/dcmtls/libsrc/Makefile.dep @@ -309,27 +309,27 @@ tlsscu.o: tlsscu.cc ../../config/include/dcmtk/config/osconfig.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmnet/include/dcmtk/dcmnet/dcompat.h \ - ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmnet/include/dcmtk/dcmnet/dcasccff.h \ ../../dcmnet/include/dcmtk/dcmnet/dndefine.h \ - ../../dcmnet/include/dcmtk/dcmnet/dimse.h \ + ../../dcmnet/include/dcmtk/dcmnet/dcasccfg.h \ + ../../dcmnet/include/dcmtk/dcmnet/assoc.h \ ../../dcmnet/include/dcmtk/dcmnet/dicom.h \ ../../dcmnet/include/dcmtk/dcmnet/cond.h \ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../dcmnet/include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ ../../dcmnet/include/dcmtk/dcmnet/lst.h \ ../../dcmnet/include/dcmtk/dcmnet/dul.h \ ../../dcmnet/include/dcmtk/dcmnet/extneg.h \ ../../dcmnet/include/dcmtk/dcmnet/dcuserid.h \ ../../dcmnet/include/dcmtk/dcmnet/dntypes.h \ - ../../dcmnet/include/dcmtk/dcmnet/assoc.h \ - ../../dcmnet/include/dcmtk/dcmnet/dcasccff.h \ - ../../dcmnet/include/dcmtk/dcmnet/dcasccfg.h \ ../../dcmnet/include/dcmtk/dcmnet/dccftsmp.h \ ../../dcmnet/include/dcmtk/dcmnet/dccfuidh.h \ ../../dcmnet/include/dcmtk/dcmnet/dccfpcmp.h \ ../../dcmnet/include/dcmtk/dcmnet/dccfrsmp.h \ ../../dcmnet/include/dcmtk/dcmnet/dccfenmp.h \ ../../dcmnet/include/dcmtk/dcmnet/dccfprmp.h \ + ../../dcmnet/include/dcmtk/dcmnet/dimse.h \ ../include/dcmtk/dcmtls/tlstrans.h \ ../../dcmnet/include/dcmtk/dcmnet/dcmtrans.h \ ../../dcmnet/include/dcmtk/dcmnet/dcmlayer.h \ diff --git a/dcmtls/libsrc/tlsopt.cc b/dcmtls/libsrc/tlsopt.cc index 5fc8fd77..b9fa2a8a 100644 --- a/dcmtls/libsrc/tlsopt.cc +++ b/dcmtls/libsrc/tlsopt.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2017-2019, OFFIS e.V. + * Copyright (C) 2017-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -83,9 +83,9 @@ void DcmTLSOptions::addTLSCommandlineOptions(OFCommandLine& cmd) cmd.addOption("--pem-keys", "-pem", "read keys and certificates as PEM file (default)"); cmd.addOption("--der-keys", "-der", "read keys and certificates as DER file"); cmd.addSubGroup("certification authority:"); - cmd.addOption("--add-cert-file", "+cf", 1, "[c]ertificate filename: string", + cmd.addOption("--add-cert-file", "+cf", 1, "[f]ilename: string", "add certificate file to list of certificates"); - cmd.addOption("--add-cert-dir", "+cd", 1, "[c]ertificate directory: string", + cmd.addOption("--add-cert-dir", "+cd", 1, "[d]irectory: string", "add certificates in d to list of certificates"); cmd.addSubGroup("security profile:"); cmd.addOption("--profile-bcp195", "+px", "BCP 195 TLS Profile (default)"); diff --git a/dcmtls/libsrc/tlsscu.cc b/dcmtls/libsrc/tlsscu.cc index 8ee25285..c4d83397 100644 --- a/dcmtls/libsrc/tlsscu.cc +++ b/dcmtls/libsrc/tlsscu.cc @@ -92,6 +92,22 @@ OFCondition DcmTLSSCU::initNetwork() return EC_IllegalCall; // TODO: need to find better error code } + /* Add trusted certificates from files and directories + */ + OFListIterator(OFString) certFile = m_trustedCertFiles.begin(); + while (certFile != m_trustedCertFiles.end()) + { + if (TCS_ok != m_tLayer->addTrustedCertificateFile( (*certFile).c_str(), m_certKeyFileFormat)) + DCMNET_WARN("Unable to load certificate file '" << *certFile << "', ignoring"); + certFile++; + } + OFListIterator(OFString) certDir = m_trustedCertDirs.begin(); + while (certDir != m_trustedCertDirs.end()) + { + if (TCS_ok != m_tLayer->addTrustedCertificateDir( (*certDir).c_str(), m_certKeyFileFormat)) + DCMNET_WARN("Unable to load certificates from directory '" << *certDir<< "', ignoring"); + } + /* If authentication of both sides (and not only encryption) is desired, * handle all associated parameters */ diff --git a/dcmtls/tests/CMakeLists.txt b/dcmtls/tests/CMakeLists.txt new file mode 100644 index 00000000..0d8c7d2b --- /dev/null +++ b/dcmtls/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +# declare executables +DCMTK_ADD_EXECUTABLE(dcmtls_tests tests tscuscptls) + +# make sure executables are linked to the corresponding libraries +DCMTK_TARGET_LINK_MODULES(dcmtls_tests dcmnet dcmtls) + +# This macro parses tests.cc and registers all tests +DCMTK_ADD_TESTS(dcmtls) diff --git a/dcmtls/tests/tests.cc b/dcmtls/tests/tests.cc new file mode 100644 index 00000000..41bb1841 --- /dev/null +++ b/dcmtls/tests/tests.cc @@ -0,0 +1,28 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmtls + * + * Authors: Michel Amat, Damien Lerat + * + * Purpose: main test program + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftest.h" + +OFTEST_REGISTER(dcmtls_scp_tls); +OFTEST_REGISTER(dcmtls_scp_pool_tls); + +OFTEST_MAIN("dcmtls") diff --git a/dcmtls/tests/tscuscptls.cc b/dcmtls/tests/tscuscptls.cc new file mode 100644 index 00000000..ef0cb223 --- /dev/null +++ b/dcmtls/tests/tscuscptls.cc @@ -0,0 +1,462 @@ +/* + * + * Copyright (C) 2019-2020, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmtls + * + * Authors: Michel Amat, Damien Lerat + * + * Purpose: TLS test for classes DcmSCP and DcmSCPPool + * + * Note: This test will fail after 2029-02-25 due to certificate expiry. + * The keys embedded in this file should be replaced then (see below). + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/ofstd/oftimer.h" +#include "dcmtk/oflog/consap.h" +#include "dcmtk/dcmnet/scp.h" +#include "dcmtk/dcmnet/scu.h" +#include "dcmtk/dcmnet/scppool.h" +#include "dcmtk/dcmnet/dcmlayer.h" +#include "dcmtk/dcmtls/tlsscu.h" + +#ifdef WITH_THREADS + +/** Method that ensures that the current thread is actually sleeping for the + * defined number of seconds (at least). + * The problem with the regular sleep() function called from OFStandard::sleep + * is that it might be interrupted by signals or a network timeout (depending + * on the operating system). This methods re-executes OFStandard's sleep method + * until the desired number of seconds have elapsed. + * @param sleep The number of seconds to sleep (at least) + */ +static void force_sleep(Uint32 sleep) +{ + OFTimer timer; + double elapsed = timer.getDiff(); + while (elapsed < (double)sleep) + { + // Use ceiling since otherwise we could wait too short + OFStandard::sleep(OFstatic_cast(unsigned int, ceil(sleep-elapsed))); + elapsed = timer.getDiff(); + } +} + + +/** TestSCP derived from DcmSCP in order to test TLS functionality + * through function setTransportLayer of DcmSCPConfig. + * + * Additionally the SCP derives from OFThread in order to construct the + * test case (i.e. send data with SCU at the same time and check results). + */ +struct TestSCP: DcmSCP, OFThread +{ + /** Constructor + */ + TestSCP() : + DcmSCP(), + m_listen_result(EC_NotYetImplemented), // value indicating "not set" + m_set_stop_after_assoc(OFFalse), + m_set_stop_after_timeout(OFFalse) + { + } + + /** Clear settings + */ + void clear() + { + m_listen_result = EC_NotYetImplemented; + m_set_stop_after_assoc = OFFalse; + m_set_stop_after_timeout = OFFalse; + } + + /** Overwrite method from DcmSCP in order to test feature to stop after current + * association. + * @return Returns value of m_set_stop_after_assoc + */ + virtual OFBool stopAfterCurrentAssociation() + { + return m_set_stop_after_assoc; + } + + /** Overwrite method from DcmSCP in order to test feature to stop after + * the SCP's connection timeout occurred in non-blocking mode. + * @return Returns value of m_set_stop_after_timeout + */ + virtual OFBool stopAfterConnectionTimeout() + { + return m_set_stop_after_timeout; + } + + /// The result returned my SCP's listen() method + OFCondition m_listen_result; + /// If set, the SCP should stop after the currently running association + OFBool m_set_stop_after_assoc; + /// If set, the SCP should stop after TCP timeout occurred in non-blocking mode + OFBool m_set_stop_after_timeout; + + /** Method called by OFThread to start SCP operation. Starts listen() loop of DcmSCP. + */ + virtual void run() + { + m_listen_result = listen(); + } + +}; + +// -------------- End of class TestSCP ------------------------- + +struct TestPool : DcmSCPPool<>, OFThread +{ + OFCondition result; +protected: + void run() + { + result = listen(); + } +}; + +// -------------- End of class TestPool ------------------------- + +#ifdef WITH_OPENSSL + +struct TestTLSSCU : DcmTLSSCU, OFThread +{ + OFCondition result; +protected: + void run() + { + OFCHECK(negotiateAssociation().good()); + result = sendECHORequest(0); + releaseAssociation(); + } +}; + +// -------------- End of class TestTLSSCU ------------------------- + + +#define PRIVATE_KEY_FILENAME "privkey.pem" +#define PUBLIC_SELFSIGNED_CERT_FILENAME "pubselfsignedcert.pem" +#define PRIVATE_KEY_PWD "testDcmtk!" + + +/** Method write_temp_key_cert_files writes private key and public certificate files, + * needed by tests dcmtls_scp_tls and dcmtls_scp_pool_tls. + * It corresponds to the files generated by the following openssl command> + * > openssl req -x509 -newkey rsa:4096 -keyout PRIVATE_KEY_FILENAME -passout pass:PRIVATE_KEY_PWD + * -out PUBLIC_SELFSIGNED_CERT_FILENAME -days 3653 -subj "/C=DE/ST=DcmTls/L=Tests/O=OFFIS/OU=DCMTK/CN=dicom@offis.de" + * @note The certificate will expire on 2029-02-25. The keys should be replaced then. + */ +void write_temp_key_cert_files() +{ + const char * privKey="-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +"MIIJnDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIfH2W1N63B6wCAggA\n" +"MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECPvpj/Xqx43SBIIJSHU3VPzHDKNX\n" +"8c7vnHT1OYjeBkx6EsnzewuWIhnzDFdt1SOXgIGUZrXVcxln1t0TvyZug+zEPY7L\n" +"TxQy/pT3N81coXzFF+Pj67wOVSVOZNtoEJIPzDvKYzTHhtX40TUK8R1rLyArMD6P\n" +"cODkY+pBUOhd9BlRr1tkaMv0GTAjxv+OhJuI/hothmRtyiZelTitxb4eHRD9ycbP\n" +"bGu3nmTf/MgcPohL/PUV9PIruRGMImQN8XDrP6Ekkp5HWi4OBkZcj37fM6N6/RZ7\n" +"fB8Mc1ebk7sRlssSoiw5LNpAz8M+geUjwTljU3rGTS/KnCMVmvcsnbMahqIrTzub\n" +"I3SPfxHKm5WjeBXDlTBONMGvEzKKXYoAV6XWKkvLClhkp+oQweOAzzHk/SJJYU7s\n" +"wmnfGGrkG26HDE0sYP5BTFI6wipnWXcLmXVVN8cawqh74Tfc3HZR0KNEiIb0nox+\n" +"zWsXYHf7OVEyj72R+Vho77PcKHDsyYNdm++VwZlESbvzZkwyZRqzrzx7o93cODK+\n" +"GIrvOIHVJ6qW3U/mkLh4RG+XjZimJ1ksK3HIwQirtDrOuvHi+GaBSgp7R5niOkA+\n" +"0PIJ4FzuBvRyXLPmSZlgo5eaGs+JrdYQSLgmiXAEmlm/200u3xtW3la6FhZyR6Mc\n" +"moNdW4B+G/0Ra4KFVv/2GCT2vGHT+5bbnpgeviMxn3/k6EtYuoFS9lcHzHrKppwj\n" +"Xx9ssbSR2SgoBSuxM4/69KzkIb0Ow7Sxex7lFt7q01Qtr26Iz4lioiaozMmow362\n" +"4XQsYck8eLakC5Ygmh5hCUpD0GtdY3n+8DT9OTfUFAE8k3PHjNRTI2SPs4F4Nlbf\n" +"WSOmBnQHb3/TD39VaqLhmJMAdax3izSnjk3ePg1JKhVJnGo6saYa8iYNZgbRn1/2\n" +"Xk4++UZVGaiorRHYpXx8UcNSdGkJpE6wqki5zbUhk0YtvzYC54DA260G0aZW0BEp\n" +"PTyhLnPW4OZWJwG3rwYC11DYees030WA0gCfwess3MP+fmZQfGMIZioAG2WVMgIl\n" +"yys4HaPb5vQkjTRqTefFEvfAXxKFfFgrnWwlyzsB9A5mglQYyCl7wTQt9FiF4s5q\n" +"SODDD2Nk72RYJc+JnaARb97OWHUFcmF5MoXJdokEKm2pYa3fcJD1UaBoquufedZY\n" +"uyjnBXz7DxPV8ZhI9KYAX+3BIo6DedPUb+43WcgNXnyqI5xnX/TWeFt4kCp60WFa\n" +"Yku3Og7QIy/PTfwXNvG6yP9koOZqANwdroN8bwwS2y3f3oTkhsy0YgcQWlIPGl6d\n" +"/trbWC2EkNBQOMsE0tRxRnZcP3OOw4pHAPqv71EFUHp9gLxvGb9rMuKqcVEC53xJ\n" +"omFrlV1x8Pa4GO3t0xg1Jatx4Sly9FOi8KqfFGUiyN1NdPuBw4+gpC9F7i5RpBjW\n" +"Yrl/mqZizGNtzRNLAESGoVD/LANmVL9SKNPp9tPDsVIWtVcCBfJVietBqq1JyiKX\n" +"6hdMNaXnAPXv1G95kczGkOjFDIs2lII9ChkY4I6wes0K6n4WbC5kuf3Z/ZAedTdI\n" +"kpQxbFYi+B/95foQM5MrHXibn+SOAO0DzqfOdG0ymBn0X/oeXbgxENmF/fZqE6Ab\n" +"MdusaIy3mnut8yQI3t1Tv/Ei2WHmnXM2bTkyd5OGZK5wYYZlMDXVPBXlZ5ZgRDRv\n" +"zE8hDYp5sXjjDvzVJjMWPj80qcdjY9wvNaoCXpdVHh4zZVgnO9L/r1XrpkIxg9/E\n" +"H3sihqtpTBs6CIDoMGiKI7dkpRyyILLhxggnpf/OEbUTypaobnZ/sOMEmNw8DGR/\n" +"/2c6ECr2/j283vifz1tiEV29Y/Pb1emiW0+66Cjoge2DpHmdB+d2va98OQzaT8Z2\n" +"hBLpIZtELrSZ5DLaVQG/aK5ZS9FxwaWD/Jrj34HJ16cMMSLXH/1eg89XqUaItQ40\n" +"eGWEWdL7vhdNnhkvUqubOc6y4US3EMGm0oB+72KhlvUwrahI/lzWGlevVjstbVAb\n" +"WS/Tg5Jf5/tObUe8OxiW4+NXn/4sx5+SZ3uQRqnLOBFNWSgwE/32S4yCZQjRJZrd\n" +"aNVZybpk5iivH2nKpaA0e0iCTCuqB4ssERspyVeMlnlJ7GSYErq459dkMRWA/JtP\n" +"C9LM1iBwcZ+RgG0Rot1xWmrsjbf8DbPhCj1GqLOBJ82ehw6uKVrE2njr03aRe3yl\n" +"4oOmtrU0TwqPOW7B/8wrwLd9s/1cIxVt7YTzTuiS7f6PL6ec/d0txyCqotKhjWs3\n" +"arWskJoUoY5A1+yD8RU5QpG/gDuJ+ToPV+GXvds+aXMtTrQKtlkXUWfkd+Z2RxEm\n" +"ZGw8+pFmm0YW80KGu6qN37F5G2MMlxtpiEIAIBfpEmWZxRMFMdbiQtJuK3o3ApXJ\n" +"GcXq6qXGXX+u6mBY7VLS1U4Q9PKJJ0/v1PW+0EHA5eeq1J+ZBGhCeM8j9OZzEwRu\n" +"r66jpdxccd4goh39jyZVEQAPxuDxPXzaDiar7Bxpb5ndef1Ml0SX5fPwZq1k8btH\n" +"udKrUGptJwinQ+F6tkr2LOJlssJ8dyw+rVrTqV1mP4KMwM/2EOSCfs15gBy7fSg2\n" +"srybRUgX87hY2KhzBU2+J7VDbWiwFnZ30y05XiVXDx+4KZUlXIWSAUjHBGTTysu0\n" +"jxEN96vkEWbxzcXCZpg1Q4L2VFfeDurL7D6wbEetwW+5hoiB1k/STyI2MFNxVBUb\n" +"JSTj/KA3Ki3V9wd+YZrOH7HHn1jTzn8QnoP5xvB/uJ9Sn1AWtmawLchg9D3eVSEX\n" +"ggQFSbylGhe+aEHnZwUjDtfvjY++CcurnMSLG2pyHxjzeevhtZg8TfJ7AMHdejBA\n" +"PYnQARJ8Pig7m/D5KNzGaP4i0lQzUMs0+e6UIX82n56Qugy7Wrw2+OV0njG1iDzQ\n" +"lXaYEFs4DPk4ATPrxFZlNpOW+VjAwU+GrKvYkRu2kYwAz3AdsbBv1Gq3o0vx5EEM\n" +"36Z13eCtP1N35M9oSFtfh2q7Yu0+xqNZ6Iy4vuxiARp4T7nzv3Q39O+0rC+YDGw3\n" +"Eh5nzkv/KOALmJSPv2ZLZ/lPH+5DW8Khg9YOJpB1q0CDQCuxBGdY0Sh54G6xPNfk\n" +"DbepXf+ja9mUcs6u07JXLeSgJjdkwu5Grj2Bbszfn7fL2fjoZgxTU2fUG5DcWDDV\n" +"hVZ9bZ9R94uD1HuG7IB7SQ==\n" +"-----END ENCRYPTED PRIVATE KEY-----"; + const size_t lenPrivKey = 3413; + FILE *privKeyFile = fopen(PRIVATE_KEY_FILENAME, "wb"); + OFCHECK(privKeyFile); + OFCHECK(lenPrivKey == fwrite(privKey, 1, lenPrivKey, privKeyFile)); + fclose(privKeyFile); + + const char* pubSelfSIgnedCert = + "-----BEGIN CERTIFICATE-----\n" +"MIIFpDCCA4ygAwIBAgIJAJRhU6soYQspMA0GCSqGSIb3DQEBCwUAMGcxCzAJBgNV\n" +"BAYTAkRFMQ8wDQYDVQQIDAZEY21UbHMxDjAMBgNVBAcMBVRlc3RzMQ4wDAYDVQQK\n" +"DAVPRkZJUzEOMAwGA1UECwwFRENNVEsxFzAVBgNVBAMMDmRpY29tQG9mZmlzLmRl\n" +"MB4XDTE5MDIyNTE0MjY0NVoXDTI5MDIyNTE0MjY0NVowZzELMAkGA1UEBhMCREUx\n" +"DzANBgNVBAgMBkRjbVRsczEOMAwGA1UEBwwFVGVzdHMxDjAMBgNVBAoMBU9GRklT\n" +"MQ4wDAYDVQQLDAVEQ01USzEXMBUGA1UEAwwOZGljb21Ab2ZmaXMuZGUwggIiMA0G\n" +"CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC+YYUnYLhLIuhizqUUO4KtzaKmqJ4z\n" +"Y5mn9H9J0U721C932F702CX38KhZOMRc/7C0cNxdYWDFS7iEjl90kwNmfkdVK8Xj\n" +"dLQ6GVTjvkVI6caeQBe3MgSvVRtczmhMqgP8DoNFSP7/OUTTcTcoHquoVIrViCOH\n" +"8vc/6mfBFA5qsoGDwi3A/LgUh/mNHqAZqAkomEzmHihNrM9RA8a+7doqjNf7IrQU\n" +"Hx7ubK+RozprXvqMTKGddy+gbbmFzCyWLgDC2ak25p1qMNVqDlZYhrfV+Q0M7fQG\n" +"OJw97SLjyHXT9P93IWO+WbLCdSmj/GBIx/nLMzRSVUbPPvUm37uhy2mSfgIhE8w8\n" +"ybVnXRLJdxUyHwpZVm+UktCPv/IU8LdgxA1sKx7+S/7BgwIS0rXX3O3yeB1z/dFS\n" +"kT44Ju+Ze8MAPxVoyWbF+SaKmy9LcsRpjjIusJLTDT3W1Pw+AymYDt0BKq5rDnd4\n" +"gx/dKuRd/921GFAnrZE86rmWbvTuqYGCYeaJfRnhCDmjWLgq/jlrc37fTv2TJXF7\n" +"TGNjkfGsjS1StC9IOnGXyhV0klvK5xxPvIGVHUbVi2bXDW9HUTmtZ6O0vFM7NgRh\n" +"UimndmrLbEJJGNGG36h5kIMe5xo7C99utu+d077itL4ZPcOyeeEHXaObjxQEzQ8x\n" +"RnkDOWzIDTU9ZQIDAQABo1MwUTAdBgNVHQ4EFgQU84HK6/XZJXpkS53bNQSma5YR\n" +"QIUwHwYDVR0jBBgwFoAU84HK6/XZJXpkS53bNQSma5YRQIUwDwYDVR0TAQH/BAUw\n" +"AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAdNRVhkbUS77PlG6TvwYBhRwijy0F3rUX\n" +"BVs4MidSaK8V9Cxa/m018GV0xoz52zIibLUiKLvRUNo3qS24Gbfbh9fdKoIBaTpG\n" +"ike3lS19ddovqQE6WsTTQWjbVP5+B4BVvGbqJNBUFI1vn8dxHFCmWDWqQJy44PqF\n" +"bp88vegFc51dTsrWVWfvTVUP56vmINm2EnvCHEJjQXp7AODlvanC358oJ18YWHzX\n" +"WgGqTE7J4Eab9lmRWMb+ArHvVqwXm5aIFAl/JJ3faJIgW1pqGyKnlQYeiQOOy+YG\n" +"pXCqUxiTMyWP27hoCMG5v3IXdbmIXedD6CwAV0yq6uZUz62g23rXaJiG0wILWMP0\n" +"xzPGnBJHz7VmXMPX1Fs8AxgHZn41N1LCT1BmnFMPmTQb4v/eHSihYHVORkvhdwQu\n" +"LJxKz8oawnka6n9UXF+rVdJjXCeYEA5Y9ThW6Qio3vjrFR5vX70EuVlu/bXqSg3J\n" +"tw+7Gn0C1XfjBtnRJPcSKdBhrkooB2Kl6nkgxy1yTyOXvG1xLeJgJw6/MiCuFu5g\n" +"DZRABWjQPrqv8rFyYm7jwa8sTAppmANazi6SsUGC27cXICVGw3zP7FrXI3jerMkv\n" +"LN+tQ/fnbPFx0kM8PW8Fx6/ns51MMzDZkCdD8yM/Bg74culg20rr25MAa/L0VGq8\n" +"x+yqEeQzzYQ=\n" +"-----END CERTIFICATE-----"; + const size_t lenPubSelfSignedCert = 2016; + FILE *pubSelfSignedCertFile = fopen(PUBLIC_SELFSIGNED_CERT_FILENAME, "wb"); + OFCHECK(pubSelfSignedCertFile); + OFCHECK(lenPubSelfSignedCert == fwrite(pubSelfSIgnedCert, 1, lenPubSelfSignedCert, pubSelfSignedCertFile)); + fclose(pubSelfSignedCertFile); +} + +// Function for initialization of logs with console appender +void initLogs() +{ + const char * const LOG_PATTERN_LAYOUT = "%D{%Y-%m-%d %H:%M:%S.%q} %5p: %m%n"; + OFunique_ptr < dcmtk::log4cplus::Layout > layout(new dcmtk::log4cplus::PatternLayout(LOG_PATTERN_LAYOUT)); + dcmtk::log4cplus::SharedAppenderPtr console(new dcmtk::log4cplus::ConsoleAppender(OFTrue /* logToStdErr */, OFTrue /* immediateFlush */)); + console->setLayout(OFmove(layout)); + dcmtk::log4cplus::Logger log = dcmtk::log4cplus::Logger::getRoot(); + log.removeAllAppenders(); + log.addAppender(console); + log.setLogLevel(OFLogger::DEBUG_LOG_LEVEL); +} + + +// Test case that checks server scp tls connection +OFTEST_FLAGS(dcmtls_scp_tls, EF_None) +{ + /// Write key and cert files + write_temp_key_cert_files(); + + /// Init logs + initLogs(); + + /// Init scp tls layer + DcmTransportLayerStatus result; + DcmTLSTransportLayer scpTlsLayer(NET_ACCEPTOR, NULL, OFTrue); + scpTlsLayer.setPrivateKeyPasswd(PRIVATE_KEY_PWD); + result = scpTlsLayer.setPrivateKeyFile(PRIVATE_KEY_FILENAME, DCF_Filetype_PEM); + OFCHECK(result == TCS_ok); + result = scpTlsLayer.setCertificateFile(PUBLIC_SELFSIGNED_CERT_FILENAME, DCF_Filetype_PEM); + OFCHECK(result == TCS_ok); + OFCHECK(scpTlsLayer.checkPrivateKeyMatchesCertificate()); + scpTlsLayer.setCertificateVerification(DCV_ignoreCertificate); + + /// Init and run Scp server with tls + TestSCP scp; + DcmSCPConfig& config = scp.getConfig(); + config.setPort(11112); + config.setAETitle("ACCEPTOR"); + config.setACSETimeout(30); + config.setConnectionTimeout(1); + config.setMaxReceivePDULength(16856); + config.setHostLookupEnabled(false); + config.setConnectionBlockingMode(DUL_NOBLOCK); + config.setRespondWithCalledAETitle("REQUESTOR"); + OFList xfers; + xfers.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCHECK(config.addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_SCP).good()); + + config.setTransportLayer(&scpTlsLayer); + scp.start(); + + // Ensure server is up and listening + force_sleep(1); + + // Configure SCU and run it against SCP + DcmTLSSCU scu; + scu.setMaxReceivePDULength(16856); + scu.setDIMSEBlockingMode(DIMSE_NONBLOCKING); + scu.setDIMSETimeout(300); + scu.setACSETimeout(30); + scu.setPeerAETitle("ACCEPTOR"); + scu.setAETitle("REQUESTOR"); + scu.setPeerHostName("localhost"); + scu.setPeerPort(11112); + + scu.enableAuthentication(PRIVATE_KEY_FILENAME, PUBLIC_SELFSIGNED_CERT_FILENAME, PRIVATE_KEY_PWD, DCF_Filetype_PEM, DCF_Filetype_PEM); + scu.setPeerCertVerification(DCV_ignoreCertificate); + + OFCHECK(scu.addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_SCU).good()); + + OFCHECK(scu.initNetwork().good()); + OFCHECK(scu.negotiateAssociation().good()); + + scp.m_set_stop_after_assoc = OFTrue; + scp.m_set_stop_after_timeout = OFTrue; + if (scu.isConnected()) + OFCHECK(scu.releaseAssociation().good()); + scp.join(); +} + + +// Test case that checks server scp tls connection +OFTEST_FLAGS(dcmtls_scp_pool_tls, EF_None) +{ + /// Write key and cert files + write_temp_key_cert_files(); + + /// Init logs + initLogs(); + + /// Init scp tls layer + DcmTransportLayerStatus result; + DcmTLSTransportLayer scpTlsLayer(NET_ACCEPTOR, NULL, OFTrue); + scpTlsLayer.setPrivateKeyPasswd(PRIVATE_KEY_PWD); + result = scpTlsLayer.setPrivateKeyFile(PRIVATE_KEY_FILENAME, DCF_Filetype_PEM); + OFCHECK(result == TCS_ok); + result = scpTlsLayer.setCertificateFile(PUBLIC_SELFSIGNED_CERT_FILENAME, DCF_Filetype_PEM); + OFCHECK(result == TCS_ok); + OFCHECK(scpTlsLayer.checkPrivateKeyMatchesCertificate()); + scpTlsLayer.setCertificateVerification(DCV_ignoreCertificate); + + /// Init and run Scp server with tls + TestPool pool; + DcmSCPConfig& config = pool.getConfig(); + config.setPort(11112); + config.setAETitle("ACCEPTOR"); + config.setACSETimeout(30); + config.setConnectionTimeout(1); + config.setMaxReceivePDULength(16856); + config.setHostLookupEnabled(false); + config.setConnectionBlockingMode(DUL_NOBLOCK); + config.setRespondWithCalledAETitle("REQUESTOR"); + OFList xfers; + xfers.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCHECK(config.addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_DEFAULT).good()); + config.setTransportLayer(&scpTlsLayer); + pool.setMaxThreads(20); + pool.start(); + + // Ensure server is up and listening + force_sleep(1); + + OFVector scus(20); + OFVector scuTlsLayers; + for (OFVector::iterator it1 = scus.begin(); it1 != scus.end(); ++it1) + { + *it1 = new TestTLSSCU; + (*it1)->setMaxReceivePDULength(16856); + (*it1)->setDIMSEBlockingMode(DIMSE_NONBLOCKING); + (*it1)->setDIMSETimeout(300); + (*it1)->setACSETimeout(30); + (*it1)->setPeerAETitle("ACCEPTOR"); + (*it1)->setAETitle("REQUESTOR"); + (*it1)->setPeerHostName("localhost"); + (*it1)->setPeerPort(11112); + (*it1)->enableAuthentication(PRIVATE_KEY_FILENAME, PUBLIC_SELFSIGNED_CERT_FILENAME, PRIVATE_KEY_PWD, DCF_Filetype_PEM, DCF_Filetype_PEM); + (*it1)->setPeerCertVerification(DCV_ignoreCertificate); + + OFList ts; + ts.push_back(UID_LittleEndianImplicitTransferSyntax); + OFCHECK((*it1)->addPresentationContext(UID_VerificationSOPClass, ts, ASC_SC_ROLE_SCU).good()); + (*it1)->initNetwork(); + } + + // "ensure" the pool is initialized before any SCU starts connecting to it. The initialization + // can take a couple of seconds on older systems, e.g. debian i368. + force_sleep(5); + + for (OFVector::const_iterator it2 = scus.begin(); it2 != scus.end(); ++it2) + { + (*it2)->start(); + } + + for (OFVector::iterator it3 = scus.begin(); it3 != scus.end(); ++it3) + { + (*it3)->join(); + OFCHECK((*it3)->result.good()); + delete *it3; + } + + for (OFVector::iterator it4 = scuTlsLayers.begin(); it4 != scuTlsLayers.end(); ++it4) + { + delete *it4; + } + + pool.stopAfterCurrentAssociations(); + pool.join(); +} + +#endif // WITH_OPENSSL + +#endif // WITH_THREADS + +#if (!defined(WITH_THREADS)) || (!defined(WITH_OPENSSL)) + +// Dummy versions of the test cases. Needed to prevent ctest test failures. +OFTEST(dcmtls_scp_tls) +{ +} + +OFTEST(dcmtls_scp_pool_tls) +{ +} + +// This dummy function creates a dependency on libdcmnet that is required when compiling +// on NetBSD with libwrap support enabled and OpenSSL support disabled. Otherwise there +// would be a linker error complaining about unresolved symbols allow_severity and deny_severity. + +DcmTransportLayer *tscuscptls_dummyFunction() +{ + return new DcmTransportLayer(); +} + +#endif diff --git a/dcmtract/include/dcmtk/dcmtract/trcmeasurement.h b/dcmtract/include/dcmtk/dcmtract/trcmeasurement.h index 94cd429a..1497a24f 100644 --- a/dcmtract/include/dcmtk/dcmtract/trcmeasurement.h +++ b/dcmtract/include/dcmtk/dcmtract/trcmeasurement.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -47,7 +47,7 @@ public: { public: - // Allow read/write functions in DcmIODUtil to access class internals + /// Allow read/write functions in DcmIODUtil to access class internals friend class DcmIODUtil; /** Create TrcMeasurement::Values from minimal data. @@ -111,7 +111,7 @@ public: Values(); }; - // Allow read/write functions in DcmIODUtil to access class internals + /// Allow read/write functions in DcmIODUtil to access class internals friend class DcmIODUtil; /** Create TrcMeasurement from minimal data diff --git a/dcmtract/include/dcmtk/dcmtract/trcmodtractresults.h b/dcmtract/include/dcmtk/dcmtract/trcmodtractresults.h index 97a7110e..b55b33d3 100644 --- a/dcmtract/include/dcmtk/dcmtract/trcmodtractresults.h +++ b/dcmtract/include/dcmtk/dcmtract/trcmodtractresults.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -96,6 +96,7 @@ public: /** Return references to images that contributed to the Tractography Results * object. The references is populated from the content of the Referenced * Instance Sequence (and will be used for populating it when writing) + * @return Reference to IODReferences */ virtual IODReferences& getReferencedInstances(); diff --git a/dcmtract/include/dcmtk/dcmtract/trcstatistic.h b/dcmtract/include/dcmtk/dcmtract/trcstatistic.h index 98dab552..ecf47820 100644 --- a/dcmtract/include/dcmtk/dcmtract/trcstatistic.h +++ b/dcmtract/include/dcmtk/dcmtract/trcstatistic.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2017, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -45,7 +45,7 @@ class DCMTK_DCMTRACT_EXPORT TrcStatistic public: - // Allow read/write functions in DcmIODUtil to access class internals + /// Allow read/write functions in DcmIODUtil to access class internals friend class DcmIODUtil; /** Constructor diff --git a/dcmtract/include/dcmtk/dcmtract/trctrack.h b/dcmtract/include/dcmtk/dcmtract/trctrack.h index a18409d0..3b57cf12 100644 --- a/dcmtract/include/dcmtk/dcmtract/trctrack.h +++ b/dcmtract/include/dcmtk/dcmtract/trctrack.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -37,7 +37,7 @@ class DCMTK_DCMTRACT_EXPORT TrcTrack public: - // Allow read/write functions in DcmIODUtil to access class internals + /// Allow read/write functions in DcmIODUtil to access class internals friend class DcmIODUtil; /** Create TrcTrack object from required data @@ -115,6 +115,7 @@ public: virtual size_t getTrackData(const Float32*& data) const; /** Get Number of data points + * @return The number of data points */ virtual size_t getNumDataPoints(); diff --git a/dcmtract/include/dcmtk/dcmtract/trctrackset.h b/dcmtract/include/dcmtk/dcmtract/trctrackset.h index d465e5f9..97bcf9d7 100644 --- a/dcmtract/include/dcmtk/dcmtract/trctrackset.h +++ b/dcmtract/include/dcmtk/dcmtract/trctrackset.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -47,7 +47,7 @@ class DCMTK_DCMTRACT_EXPORT TrcTrackSet public: - // Allow read/write functions in DcmIODUtil to access class internals + /// Allow read/write functions in DcmIODUtil to access class internals friend class DcmIODUtil; /** Create TrcTrackSet object by proving required data @@ -314,6 +314,7 @@ public: * @param value The statistical value * @param statistic Returns the created statistic, if successful. NULL * otherwise + * @return EC_Normal if successful, error otherwise */ virtual OFCondition addTrackSetStatistic(const CodeSequenceMacro& typeCode, const CodeSequenceMacro& typeModifierCode, diff --git a/dcmtract/libsrc/Makefile.dep b/dcmtract/libsrc/Makefile.dep index 41c5806d..f341392d 100644 --- a/dcmtract/libsrc/Makefile.dep +++ b/dcmtract/libsrc/Makefile.dep @@ -9,15 +9,17 @@ trcmeasurement.o: trcmeasurement.cc \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -43,29 +45,26 @@ trcmeasurement.o: trcmeasurement.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmtract/trcmeasurement.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ @@ -126,7 +125,9 @@ trcmeasurement.o: trcmeasurement.cc \ trcmodtractresults.o: trcmodtractresults.cc \ ../../config/include/dcmtk/config/osconfig.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/oftypes.h \ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ ../../ofstd/include/dcmtk/ofstd/ofcast.h \ @@ -134,14 +135,13 @@ trcmodtractresults.o: trcmodtractresults.cc \ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -167,29 +167,27 @@ trcmodtractresults.o: trcmodtractresults.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmtract/trcmodtractresults.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ @@ -262,15 +260,17 @@ trcstatistic.o: trcstatistic.cc \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -296,29 +296,26 @@ trcstatistic.o: trcstatistic.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmtract/trcstatistic.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ @@ -386,15 +383,17 @@ trctrack.o: trctrack.cc ../../config/include/dcmtk/config/osconfig.h \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -420,29 +419,26 @@ trctrack.o: trctrack.cc ../../config/include/dcmtk/config/osconfig.h \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmtract/trctrack.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../include/dcmtk/dcmtract/trctypes.h \ @@ -462,14 +458,16 @@ trctrackset.o: trctrackset.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -493,29 +491,26 @@ trctrackset.o: trctrackset.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../include/dcmtk/dcmtract/trctrackset.h \ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ @@ -587,15 +582,17 @@ trctractographyresults.o: trctractographyresults.cc \ ../../ofstd/include/dcmtk/ofstd/ofstream.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ - ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ ../../ofstd/include/dcmtk/ofstd/ofstring.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ - ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ - ../../ofstd/include/dcmtk/ofstd/ofthread.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ ../../ofstd/include/dcmtk/ofstd/ofcond.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../ofstd/include/dcmtk/ofstd/oflimits.h \ + ../../config/include/dcmtk/config/arith.h \ + ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ ../../oflog/include/dcmtk/oflog/oflog.h \ ../../oflog/include/dcmtk/oflog/logger.h \ @@ -621,29 +618,26 @@ trctractographyresults.o: trctractographyresults.cc \ ../../oflog/include/dcmtk/oflog/logmacro.h \ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ - ../../ofstd/include/dcmtk/ofstd/offile.h \ - ../../ofstd/include/dcmtk/ofstd/ofstd.h \ - ../../ofstd/include/dcmtk/ofstd/oflist.h \ - ../../ofstd/include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../../ofstd/include/dcmtk/ofstd/oferror.h \ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ - ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ - ../../ofstd/include/dcmtk/ofstd/ofdate.h \ - ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ - ../../ofstd/include/dcmtk/ofstd/ofmap.h \ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ - ../../dcmiod/include/dcmtk/dcmiod/cielabutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \ ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ @@ -698,19 +692,19 @@ trctractographyresults.o: trctractographyresults.cc \ ../../dcmdata/include/dcmtk/dcmdata/dcvrol.h \ ../../dcmdata/include/dcmtk/dcmdata/dcvrov.h \ ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ - ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \ ../include/dcmtk/dcmtract/trctractographyresults.h \ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ ../../ofstd/include/dcmtk/ofstd/ofoption.h \ ../../ofstd/include/dcmtk/ofstd/ofalign.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ - ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ - ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ - ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \ ../include/dcmtk/dcmtract/trctypes.h ../include/dcmtk/dcmtract/trcdef.h \ diff --git a/dcmtract/libsrc/trctrack.cc b/dcmtract/libsrc/trctrack.cc index 3bf3662c..f7aac1d7 100644 --- a/dcmtract/libsrc/trctrack.cc +++ b/dcmtract/libsrc/trctrack.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2016-2018, Open Connections GmbH + * Copyright (C) 2016-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by @@ -73,6 +73,7 @@ void TrcTrack::resetRules() OFCondition TrcTrack::check(const OFBool quiet) { + OFCondition result; // Report errors but ignore them IODComponent::check(quiet); const Float32* data = NULL; @@ -84,27 +85,26 @@ OFCondition TrcTrack::check(const OFBool quiet) { if (count % 3 == 0) { - return EC_Normal; + result = EC_Normal; } else { DCMTRACT_ERROR("Point Coordinates Data must have x,y,z coordinates for every point but has length: " << count); - return IOD_EC_InvalidElementValue; + result = IOD_EC_InvalidElementValue; } } else { DCMTRACT_ERROR("Point Coordinates Data empty"); - return IOD_EC_InvalidElementValue; + result = IOD_EC_InvalidElementValue; } } else { DCMTRACT_ERROR("Point Coordinates Data element missing"); - return IOD_EC_MissingAttribute; + result = IOD_EC_MissingAttribute; } - // should never get here - return EC_Normal; + return result; } @@ -278,6 +278,7 @@ OFCondition TrcTrack::setTrackData(const Float32* trackDataPoints, OFCondition TrcTrack::setRecommendedDisplayCIELabValues(const Uint16* colors, const size_t numColors) { + OFCondition result; if ( (numColors == 0) && (colors == NULL)) { m_Item->findAndDeleteElement(DCM_RecommendedDisplayCIELabValue); @@ -296,8 +297,6 @@ OFCondition TrcTrack::setRecommendedDisplayCIELabValues(const Uint16* colors, { return m_Item->putAndInsertUint16Array(DCM_RecommendedDisplayCIELabValueList, colors, OFstatic_cast(unsigned long, numColors * 3)); } - // should never get here - return TRC_EC_InvalidColorInformation; } diff --git a/dcmwlm/apps/wlcefs.cc b/dcmwlm/apps/wlcefs.cc index 44d496b3..71d8f57b 100644 --- a/dcmwlm/apps/wlcefs.cc +++ b/dcmwlm/apps/wlcefs.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2019, OFFIS e.V. + * Copyright (C) 1996-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -133,9 +133,6 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], cmd->addOption("--keep-char-set", "-csk", "return character set provided in file"); cmd->addSubGroup("other processing options:"); cmd->addOption("--no-sq-expansion", "-nse", "disable expansion of empty sequences in C-FIND\nrequest messages"); - cmd->addOption("--request-file-path", "-rfp", 1, "[p]ath: string", "path to store request files to"); - cmd->addOption("--request-file-format", "-rff", 1, "[f]ormat: string (default: #t.dump)", "request file name format"); - cmd->addGroup("network options:"); cmd->addSubGroup("preferred network transfer syntaxes:"); @@ -192,6 +189,11 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], cmd->addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); cmd->addOption("--disable-host-lookup", "-dhl", "disable hostname lookup"); + cmd->addGroup("output options:"); + cmd->addSubGroup("general:"); + cmd->addOption("--request-file-path", "-rfp", 1, "[p]ath: string", "path to store request files to"); + cmd->addOption("--request-file-format", "-rff", 1, "[f]ormat: string (default: #t.dump)", "request file name format"); + // Evaluate command line. prepareCmdLineArgs( argc, argv, applicationName ); if( app->parseCommandLine( *cmd, argc, argv ) ) @@ -223,6 +225,7 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], OFLog::configureFromCommandLine(*cmd, *app); + // general options #if defined(HAVE_FORK) || defined(_WIN32) cmd->beginOptionBlock(); if (cmd->findOption("--single-process")) opt_singleProcess = OFTrue; @@ -233,19 +236,15 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], #endif #endif + // input options if( cmd->findOption("--data-files-path") ) app->checkValue(cmd->getValue(opt_dfPath)); - if( cmd->findOption("--request-file-path") ) app->checkValue(cmd->getValue(opt_rfPath)); - if( cmd->findOption("--request-file-format") ) - { - app->checkDependence("--request-file-format", "--request-file-path", !opt_rfPath.empty()); - app->checkValue(cmd->getValue(opt_rfFormat)); - } cmd->beginOptionBlock(); if( cmd->findOption("--enable-file-reject") ) opt_enableRejectionOfIncompleteWlFiles = OFTrue; if( cmd->findOption("--disable-file-reject") ) opt_enableRejectionOfIncompleteWlFiles = OFFalse; cmd->endOptionBlock(); + // processing options cmd->beginOptionBlock(); if( cmd->findOption("--return-no-char-set") ) opt_returnedCharacterSet = RETURN_NO_CHARACTER_SET; if( cmd->findOption("--return-iso-ir-100") ) opt_returnedCharacterSet = RETURN_CHARACTER_SET_ISO_IR_100; @@ -254,6 +253,7 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], if( cmd->findOption("--no-sq-expansion") ) opt_noSequenceExpansion = OFTrue; + // network options cmd->beginOptionBlock(); if( cmd->findOption("--prefer-uncompr") ) opt_networkTransferSyntax = EXS_Unknown; if( cmd->findOption("--prefer-little") ) opt_networkTransferSyntax = EXS_LittleEndianExplicit; @@ -316,6 +316,14 @@ WlmConsoleEngineFileSystem::WlmConsoleEngineFileSystem( int argc, char *argv[], if( cmd->findOption("--sleep-during") ) app->checkValue(cmd->getValueAndCheckMin(opt_sleepDuringFind, 0)); if( cmd->findOption("--max-pdu") ) app->checkValue(cmd->getValueAndCheckMinMax(opt_maxPDU, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); if( cmd->findOption("--disable-host-lookup") ) dcmDisableGethostbyaddr.set(OFTrue); + + // output options + if( cmd->findOption("--request-file-path") ) app->checkValue(cmd->getValue(opt_rfPath)); + if( cmd->findOption("--request-file-format") ) + { + app->checkDependence("--request-file-format", "--request-file-path", !opt_rfPath.empty()); + app->checkValue(cmd->getValue(opt_rfFormat)); + } } // dump application information diff --git a/dcmwlm/docs/wlmscpfs.man b/dcmwlm/docs/wlmscpfs.man index f096db7b..652b214e 100644 --- a/dcmwlm/docs/wlmscpfs.man +++ b/dcmwlm/docs/wlmscpfs.man @@ -104,12 +104,6 @@ other processing options: -nse --no-sq-expansion disable expansion of empty sequences in C-FIND request messages - - -rfp --request-file-path [p]ath: string - path to store request files to - - -rff --request-file-format [f]ormat: string (default: #t.dump) - request file name format \endverbatim \subsection wlmscpfs_network_options network options @@ -188,6 +182,17 @@ other network options: disable hostname lookup \endverbatim +\subsection wlmscp_output_options output options +\verbatim +general: + + -rfp --request-file-path [p]ath: string + path to store request files to + + -rff --request-file-format [f]ormat: string (default: #t.dump) + request file name format +\endverbatim + \section wlmscpfs_notes NOTES The semantic impacts of the above mentioned options is clear for the majority @@ -508,6 +513,6 @@ It is an error if no data dictionary can be loaded. \section wlmscpfs_copyright COPYRIGHT -Copyright (C) 1996-2019 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. +Copyright (C) 1996-2020 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. */ diff --git a/dcmwlm/libsrc/wldsfs.cc b/dcmwlm/libsrc/wldsfs.cc index a2f28f16..1efb34e6 100644 --- a/dcmwlm/libsrc/wldsfs.cc +++ b/dcmwlm/libsrc/wldsfs.cc @@ -665,11 +665,11 @@ OFBool WlmDataSourceFileSystem::SetReadlock() // assign path to a local variable OFString lockname = dfPath; - // if the given path does not show a PATH_SEPERATOR at the end, append one + // if the given path does not show a PATH_SEPARATOR at the end, append one if( !lockname.empty() && lockname[lockname.length()-1] != PATH_SEPARATOR ) lockname += PATH_SEPARATOR; - // append calledApplicationEntityTitle, another PATH_SEPERATOR, + // append calledApplicationEntityTitle, another PATH_SEPARATOR, // and LOCKFILENAME to the given path (and separator) lockname += calledApplicationEntityTitle; lockname += PATH_SEPARATOR; diff --git a/dcmwlm/libsrc/wlfsim.cc b/dcmwlm/libsrc/wlfsim.cc index 5ce8f9c8..f2ae1c02 100644 --- a/dcmwlm/libsrc/wlfsim.cc +++ b/dcmwlm/libsrc/wlfsim.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1996-2018, OFFIS e.V. + * Copyright (C) 1996-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -671,8 +671,8 @@ OFBool WlmFileSystemInteractionManager::IsUniversalMatch( DcmSequenceOfItems& qu { const OFPair& key = *it; #endif - DcmElement* query = OFnullptr; - if( pQueryItem->findAndGetElement( key.first, query, OFFalse ).good() && query && !query->isUniversalMatch( normalize, normalizeWildCards && key.second ) ) + DcmElement* query_elem = OFnullptr; + if( pQueryItem->findAndGetElement( key.first, query_elem, OFFalse ).good() && query_elem && !query_elem->isUniversalMatch( normalize, normalizeWildCards && key.second ) ) return OFFalse; } @@ -685,10 +685,10 @@ OFBool WlmFileSystemInteractionManager::IsUniversalMatch( DcmSequenceOfItems& qu { const OFPair& combinedKey = *it; #endif - DcmElement* query = OFnullptr; - if( pQueryItem->findAndGetElement( combinedKey.first, query, OFFalse ).good() && query && !query->isUniversalMatch( normalize, normalizeWildCards ) ) + DcmElement* query_elem = OFnullptr; + if( pQueryItem->findAndGetElement( combinedKey.first, query_elem, OFFalse ).good() && query_elem && !query_elem->isUniversalMatch( normalize, normalizeWildCards ) ) return OFFalse; - else if( pQueryItem->findAndGetElement( combinedKey.second, query, OFFalse ).good() && query && !query->isUniversalMatch( normalize, normalizeWildCards ) ) + else if( pQueryItem->findAndGetElement( combinedKey.second, query_elem, OFFalse ).good() && query_elem && !query_elem->isUniversalMatch( normalize, normalizeWildCards ) ) return OFFalse; } @@ -702,8 +702,8 @@ OFBool WlmFileSystemInteractionManager::IsUniversalMatch( DcmSequenceOfItems& qu { const OFPair& sequenceKey = *it; #endif - DcmElement* query = OFnullptr; - if( pQueryItem->findAndGetElement( sequenceKey.first, query, OFFalse ).good() && query && query->ident() == EVR_SQ && !IsUniversalMatch( OFstatic_cast( DcmSequenceOfItems&, *query ), sequenceKey.second, normalize, normalizeWildCards ) ) + DcmElement* query_elem = OFnullptr; + if( pQueryItem->findAndGetElement( sequenceKey.first, query_elem, OFFalse ).good() && query_elem && query_elem->ident() == EVR_SQ && !IsUniversalMatch( OFstatic_cast( DcmSequenceOfItems&, *query_elem ), sequenceKey.second, normalize, normalizeWildCards ) ) return OFFalse; } } diff --git a/dcmwlm/libsrc/wlmactmg.cc b/dcmwlm/libsrc/wlmactmg.cc index 4d2f10bb..6596cd8f 100644 --- a/dcmwlm/libsrc/wlmactmg.cc +++ b/dcmwlm/libsrc/wlmactmg.cc @@ -910,7 +910,7 @@ void WlmActivityManager::RemoveProcessFromTable( int pid ) // if process can be found, delete it from list and free memory if ( ps->processId == pid ) { - processTable.remove(*it); + processTable.erase(it); delete ps; return; } diff --git a/docs/ANNOUNCE.365 b/docs/ANNOUNCE.365 new file mode 100644 index 00000000..f4d40abd --- /dev/null +++ b/docs/ANNOUNCE.365 @@ -0,0 +1,169 @@ +ANNOUNCEMENT + +Version 3.6.5 of the OFFIS DCMTK (DICOM ToolKit) software is now available for +public release. This is a minor release that includes the following changes +over the previous version 3.6.4: + +- DCMTK 3.6.5 builds correctly on older and up-to-date versions of GNU gcc + (4.4.7 to 9.2.0), Clang (3.4.2 to 9.0.0), AppleClang (11.0.0), Microsoft + Visual Studio (2008 to 2019), SunPro CC (5.14 and 5.15) and IBM XL C/C++ + (16.1.1.3). + +- Tested with the following operating systems/environments: + + - Android on arm64 + - Cygwin on x86_64 + - FreeBSD on x86_64 + - Linux on x86_64 and x86 + - MacOS X on x86_64 + - NetBSD on x86_64 + - OpenBSD on x86_64 + - OpenIndiana on x86 + - Solaris on x86 + - Windows (and MinGW) on x86_64 and x86 + + For a complete list of tested systems and compilers, see the INSTALL file. + +- GNU Autoconf is still deprecated, running 'configure' emits a warning by + default. Support for GNU Autoconf will be removed after this release. + +- Updated data dictionary, SOP Class, Frame of Reference and Transfer Syntax + UIDs for the recently approved changes to the DICOM standard (i.e. Supplements + and CPs), up to DICOM standard release DICOM 2019c plus Supplement 175 (Second + Generation Radiotherapy - C-Arm RT Treatment Modalities). + +- Added support for directory record "RADIOTHERAPY" that has been introduced + with Supplement 147 (Second Generation Radiotherapy - Prescription and Segment + Annotation). + +- Added support for the three new 64-bit integer VRs introduced with CP-1819: + Other 64-bit Very Long (OV), Signed 64-bit Very Long (SV) and Unsigned 64-bit + Very Long (UV). + +- Implemented support for the Extended BCP 195 TLS Profile, introduced with + Supplement 206, in the dcmtls module and the various TLS-enabled DCMTK tools. + +- Added option to "storescu" to rename files after processing them by appending + ".bad" or ".good" at the end of the filename. + +- Added new options to "wlmscpfs" that allow for dumping incoming C-FIND + requests to text files using a configurable directory and filename. + +- Updated automatically generated Context Group classes in "dcmsr" + (Structured Reporting) based on DICOM 2019c. Also updated the Code + definitions from the supported coding schemes such as DICOM, NCIt and UMLS. + +- Further enhanced DICOM Structured Reporting (SR) module "dcmsr": + + - Added support for the Performed Imaging Agent Administration SR IOD and the + Planned Imaging Agent Administration SR IOD introduced with Supplement 164. + + - Added support for the Synchronization Module, which is required for some SR + IODs, e.g. Procedure Log SR or Performed Imaging Agent Administration SR. + + - Added initial support for coding scheme "SCT" (SNOMED CT) by defining those + CODE_SCT_xxx code constants that are needed for the "cmr" submodule. + + - Updated SR Template classes from DCMR for the 2019b edition of the DICOM + standard, i.e. all SRT (SNOMED RT) codes were replaced by their associated + SCT (SNOMED CT) counterparts. This change was introduced with CP-1850. + + - Added new print flag PF_printEmptyCodes, which prints the text "empty code" + for empty codes instead of "invalid code". This new flag is e.g. used for + the output stream operator of the DSRCodedEntryValue class. + +- The list of elliptic curves to be negotiated as part of a TLS is now created + dynamically, i.e. it is tested at runtime which elliptic curves are supported + by the installed OpenSSL library. + +- Allow disabling Functional Group checks when writing Segmentations and + Parametric Map objects in order to speed up writing objects with many frames. + +- Added macro that enables the wide char (wchar_t*) support of the XML parser + that is part of the DCMTK (ofstd/ofxml). This support is limited to Windows + systems and still regarded as experimental (see documentation for details). + +- The tool "findscu" now always returns with a non-zero exit code when an error + occurred, e.g. when association negotiation failed. + +- CMake-related enhancements: + + - DCMTK now understands and makes use of the CMake variable CMAKE_CXX_STANDARD + when a CMake version that supports it is employed (CMake 3.1.3 and newer). + + - Added CMake option that controls whether DCMTK gets compiled using the + multi-threaded static or DLL runtime library when using MSVC on Windows. + +- Various fixes and extensions to the JPEG-LS implementation: + + - Added command line options controlling how odd-length bitstreams are + padded to even length (for compatibility with HP LOCO). + + - Added command line option that causes the decoder to store images even + though an error occurred during the decoding process, which may be helpful + for slightly truncated bitstreams. + + - Enable setting of individual JPEG-LS encoding parameters + T1, T2, T3 and RESET. + + - Various bugfixes in JPEG-LS encoder and decoder. + +- Fixed binary Segmentation object creation when width is not dividable by 8. + +- Fixed wrong DIMSE status codes A8xx (for C-STORE and C-FIND) and A800 (for + C-GET and C-MOVE), which were never defined in the official DICOM standard. + Now, the DCMTK uses the correct DIMSE status code 0122H for "SOP Class not + supported" for all DIMSE messages. + +- Fixed various issues that occurred after the official 3.6.4 release. + See CHANGES file for details. + + +Many people have contributed to this new release of DCMTK, appearing here in +alphabetical order. Thank you very much for your support! + + Victor Derks + Chinna Durai + Holger Franke + Sergei Gordey + Daniel Grieger + Bengt Gustafsson + Alexander Haderer + Peter Klotz + Brian Lucas + Mathieu Malaterre + Hans Meine + Maria Samoylova + Martin Wenger + Brian Wise + Grischa Zengel + + Andreas Gravgaard Andersen (GitHub user "agravgaard") + Hans Johnson (GitHub user "hjmjohnson") + Stefano Magni + + Forum user "AlexanderLysenko" + GitHub user "eborisch" + GitHub user "FreddyFunk" + +Members of the DCMTK Team who have worked on this release are +(in alphabetical order): + + Pedro Arizpe Gomez + Marco Eichelberg + Michael Onken + Joerg Riesmeier + Jan Schlamelcher + +Student associates: + + Nikolas Goldhammer + +Also see CREDITS file for projects and companies who have been generously +supporting DCMTK. + +The DCMTK software can be downloaded via: + + https://dicom.offis.de/dcmtk or https://www.dcmtk.org/ + +OFFIS e.V., Oldenburg, Germany, 2019-10-28 diff --git a/docs/CHANGES.320 b/docs/CHANGES.320 index 080382fc..0ffa83c1 100644 --- a/docs/CHANGES.320 +++ b/docs/CHANGES.320 @@ -387,7 +387,7 @@ Release 3.2 (Public Release - 1997.06.02) - Added improved error/warning messages and backup of existing DICOMDIR file (the backup file has the suffix .BAK and is removed if the new - DICOMDIR file is sucessfully created). + DICOMDIR file is successfully created). Affects: dcmdata/apps/dcmgpdir.cc - Fixed bug related to renaming of temporary files accross file system diff --git a/docs/CHANGES.342 b/docs/CHANGES.342 index 9e586e92..6d6df583 100644 --- a/docs/CHANGES.342 +++ b/docs/CHANGES.342 @@ -1971,7 +1971,7 @@ Release 3.4.2 (Public Release - 2000-12-20) dcmnet/libsrc/dimdump.cc dcmnet/libsrc/dimse.cc -- added optional paramter to DIMSE_storeUser that enables precise file size +- added optional parameter to DIMSE_storeUser that enables precise file size information inside the store user callback. Thanks to Mohamed Ahmed Abd Elkader for the bug report. diff --git a/docs/CHANGES.350 b/docs/CHANGES.350 index 88888fc4..9f1d583c 100644 --- a/docs/CHANGES.350 +++ b/docs/CHANGES.350 @@ -194,7 +194,7 @@ Release 3.5.0 (Public Release - 2001-06-14) dcmdata/libsrc/dcuid.cc dcmdata/libsrc/dicom.dic -- Fixed memory leak that occured when parsing of a sequence failed. +- Fixed memory leak that occurred when parsing of a sequence failed. Thanks to Harald Breitner for the bug report and fix. Affects: dcmdata/libsrc/dcsequen.cc diff --git a/docs/CHANGES.352 b/docs/CHANGES.352 index 870eeea7..8c642600 100644 --- a/docs/CHANGES.352 +++ b/docs/CHANGES.352 @@ -2421,7 +2421,7 @@ Release 3.5.2 (Public Release - 2002-12-23) - Added vitual destructor to class OFStackLink Affects: ofstd/include/ofstack.h -- Fixed memory leak that occured when compression of an image failed in +- Fixed memory leak that occurred when compression of an image failed in a compression codec. Affects: dcmdata/libsrc/dcpixel.cc diff --git a/docs/CHANGES.360 b/docs/CHANGES.360 index d3b35f17..93511a44 100644 --- a/docs/CHANGES.360 +++ b/docs/CHANGES.360 @@ -3499,7 +3499,7 @@ Release 3.6.0 (Public Release - 2011-01-06) Affects: dcmdata/libsrc/dcitem.cc - Fixed memory leak in assignment operators of DcmItem and DcmSequenceOfItems. - Replaced all code occurences of cleaning all elements from internal lists to + Replaced all code occurrences of cleaning all elements from internal lists to newly introduced function in DcmList. Affects: dcmdata/libsrc/dcitem.cc dcmdata/libsrc/dcsequen.cc @@ -9311,7 +9311,7 @@ Release 3.6.0 (Public Release - 2011-01-06) Affects: dcmdata/libsrc/private.dic - Fixed memory leak in DIMSE_receiveDataSetInMemory when parameter dataObject - was passed as NULL and an error condition occured. + was passed as NULL and an error condition occurred. Thanks to Michael Doppler for the report and fix. Affects: dcmnet/libsrc/dimse.cc diff --git a/docs/CHANGES.362 b/docs/CHANGES.362 index 5d00a1e2..658707b4 100644 --- a/docs/CHANGES.362 +++ b/docs/CHANGES.362 @@ -12024,7 +12024,7 @@ Release 3.6.2 (Public Release - 2017-07-14) dcmsr/tests/tsrdoctr.cc dcmsr/tests/tsrtree.cc -- Avoid seperator if time component is empty: +- Avoid separator if time component is empty: Avoid separator between date and time component of a "DateTime" value if the latter is empty. Before, there was a trailing space in the resulting string. Affects: dcmdata/include/dcmtk/dcmdata/dcvrdt.h @@ -19120,7 +19120,7 @@ Release 3.6.2 (Public Release - 2017-07-14) **** Changes from 2013.01.04 (onken) - Made DcmAssociationConfiguration and underlying classes copy-constructable. - Replaced all occurences of DcmSimpleMap with OFMap. + Replaced all occurrences of DcmSimpleMap with OFMap. Affects: dcmnet/apps/Makefile.dep dcmnet/include/dcmtk/dcmnet/dcasccfg.h dcmnet/include/dcmtk/dcmnet/dccfenmp.h diff --git a/docs/CHANGES.363 b/docs/CHANGES.363 index f7ef368f..5fb5e64a 100644 --- a/docs/CHANGES.363 +++ b/docs/CHANGES.363 @@ -482,7 +482,7 @@ Release 3.6.3 (Public Minor Release - 2018-02-05) Affects: dcmdata/libsrc/dcvrof.cc - Fixed buffer overrrun in DcmOtherFloat::writeXML(): - Fixed buffer overrun in DcmOtherFloat::writeXML() that occured if + Fixed buffer overrun in DcmOtherFloat::writeXML() that occurred if an invalid element with VR=OF and Length=2 is present in the dataset that is converted to XML. Thanks to Gwan Yeong Kim for the bug report. diff --git a/docs/CHANGES.366 b/docs/CHANGES.366 new file mode 100644 index 00000000..f3f46c9f --- /dev/null +++ b/docs/CHANGES.366 @@ -0,0 +1,2782 @@ + +Release 3.6.6 (Public Minor Release - 2021-01-14) + +**** Changes from 2021.01.14 (onken) + +- Updated release date in INSTALL file and for autoconf. + Affects: INSTALL + public/config/configure + public/config/configure.in + +- Final changes for Release 3.6.6. + Affects: ANNOUNCE + CMake/dcmtkPrepare.cmake + CREDITS + docs/CHANGES.366 + doxygen/manpages/man1/cda2dcm.1 + doxygen/manpages/man1/dcm2json.1 + doxygen/manpages/man1/dcm2pdf.1 + doxygen/manpages/man1/dcm2pnm.1 + doxygen/manpages/man1/dcm2xml.1 + doxygen/manpages/man1/dcmcjpeg.1 + doxygen/manpages/man1/dcmcjpls.1 + doxygen/manpages/man1/dcmconv.1 + doxygen/manpages/man1/dcmcrle.1 + doxygen/manpages/man1/dcmdjpeg.1 + doxygen/manpages/man1/dcmdjpls.1 + doxygen/manpages/man1/dcmdrle.1 + doxygen/manpages/man1/dcmdspfn.1 + doxygen/manpages/man1/dcmdump.1 + doxygen/manpages/man1/dcmftest.1 + doxygen/manpages/man1/dcmgpdir.1 + doxygen/manpages/man1/dcmicmp.1 + doxygen/manpages/man1/dcmj2pnm.1 + doxygen/manpages/man1/dcml2pnm.1 + doxygen/manpages/man1/dcmmkcrv.1 + doxygen/manpages/man1/dcmmkdir.1 + doxygen/manpages/man1/dcmmklut.1 + doxygen/manpages/man1/dcmodify.1 + doxygen/manpages/man1/dcmp2pgm.1 + doxygen/manpages/man1/dcmprscp.1 + doxygen/manpages/man1/dcmprscu.1 + doxygen/manpages/man1/dcmpschk.1 + doxygen/manpages/man1/dcmpsmk.1 + doxygen/manpages/man1/dcmpsprt.1 + doxygen/manpages/man1/dcmpsrcv.1 + doxygen/manpages/man1/dcmpssnd.1 + doxygen/manpages/man1/dcmqridx.1 + doxygen/manpages/man1/dcmqrscp.1 + doxygen/manpages/man1/dcmqrti.1 + doxygen/manpages/man1/dcmquant.1 + doxygen/manpages/man1/dcmrecv.1 + doxygen/manpages/man1/dcmscale.1 + doxygen/manpages/man1/dcmsend.1 + doxygen/manpages/man1/dcmsign.1 + doxygen/manpages/man1/dcod2lum.1 + doxygen/manpages/man1/dconvlum.1 + doxygen/manpages/man1/drtdump.1 + doxygen/manpages/man1/dsr2html.1 + doxygen/manpages/man1/dsr2xml.1 + doxygen/manpages/man1/dsrdump.1 + doxygen/manpages/man1/dump2dcm.1 + doxygen/manpages/man1/echoscu.1 + doxygen/manpages/man1/findscu.1 + doxygen/manpages/man1/getscu.1 + doxygen/manpages/man1/img2dcm.1 + doxygen/manpages/man1/movescu.1 + doxygen/manpages/man1/pdf2dcm.1 + doxygen/manpages/man1/stl2dcm.1 + doxygen/manpages/man1/storescp.1 + doxygen/manpages/man1/storescu.1 + doxygen/manpages/man1/termscu.1 + doxygen/manpages/man1/wlmscpfs.1 + doxygen/manpages/man1/xml2dcm.1 + doxygen/manpages/man1/xml2dsr.1 + + +**** Changes from 2021.01.07 (onken) + +- Updated ANNOUNCE for Release 3.6.6 + Affects: ANNOUNCE + +- Prepared source tree for DCMTK release 3.6.6. + Affects: ANNOUNCE + CMake/dcmtkPrepare.cmake + COPYRIGHT + CREDITS + INSTALL + VERSION + config/configure + config/configure.in + docs/CHANGES.366 + doxygen/manpages/man1/cda2dcm.1 + doxygen/manpages/man1/dcm2json.1 + doxygen/manpages/man1/dcm2pdf.1 + doxygen/manpages/man1/dcm2pnm.1 + doxygen/manpages/man1/dcm2xml.1 + doxygen/manpages/man1/dcmcjpeg.1 + doxygen/manpages/man1/dcmcjpls.1 + doxygen/manpages/man1/dcmconv.1 + doxygen/manpages/man1/dcmcrle.1 + doxygen/manpages/man1/dcmdjpeg.1 + doxygen/manpages/man1/dcmdjpls.1 + doxygen/manpages/man1/dcmdrle.1 + doxygen/manpages/man1/dcmdspfn.1 + doxygen/manpages/man1/dcmdump.1 + doxygen/manpages/man1/dcmftest.1 + doxygen/manpages/man1/dcmgpdir.1 + doxygen/manpages/man1/dcmicmp.1 + doxygen/manpages/man1/dcmj2pnm.1 + doxygen/manpages/man1/dcml2pnm.1 + doxygen/manpages/man1/dcmmkcrv.1 + doxygen/manpages/man1/dcmmkdir.1 + doxygen/manpages/man1/dcmmklut.1 + doxygen/manpages/man1/dcmodify.1 + doxygen/manpages/man1/dcmp2pgm.1 + doxygen/manpages/man1/dcmprscp.1 + doxygen/manpages/man1/dcmprscu.1 + doxygen/manpages/man1/dcmpschk.1 + doxygen/manpages/man1/dcmpsmk.1 + doxygen/manpages/man1/dcmpsprt.1 + doxygen/manpages/man1/dcmpsrcv.1 + doxygen/manpages/man1/dcmpssnd.1 + doxygen/manpages/man1/dcmqridx.1 + doxygen/manpages/man1/dcmqrscp.1 + doxygen/manpages/man1/dcmqrti.1 + doxygen/manpages/man1/dcmquant.1 + doxygen/manpages/man1/dcmrecv.1 + doxygen/manpages/man1/dcmscale.1 + doxygen/manpages/man1/dcmsend.1 + doxygen/manpages/man1/dcmsign.1 + doxygen/manpages/man1/dcod2lum.1 + doxygen/manpages/man1/dconvlum.1 + doxygen/manpages/man1/drtdump.1 + doxygen/manpages/man1/dsr2html.1 + doxygen/manpages/man1/dsr2xml.1 + doxygen/manpages/man1/dsrdump.1 + doxygen/manpages/man1/dump2dcm.1 + doxygen/manpages/man1/echoscu.1 + doxygen/manpages/man1/findscu.1 + doxygen/manpages/man1/getscu.1 + doxygen/manpages/man1/img2dcm.1 + doxygen/manpages/man1/movescu.1 + doxygen/manpages/man1/pdf2dcm.1 + doxygen/manpages/man1/stl2dcm.1 + doxygen/manpages/man1/storescp.1 + doxygen/manpages/man1/storescu.1 + doxygen/manpages/man1/termscu.1 + doxygen/manpages/man1/wlmscpfs.1 + doxygen/manpages/man1/xml2dcm.1 + doxygen/manpages/man1/xml2dsr.1 + +**** Changes from 2020.12.29 (eichelberg) + +- Minor bug fixes in dcmpsprt application. + The --img-request-size option now works correctly when the target printer + is not explicitly specified with --printer. Furthermore, the --overlay + option now correctly processes PBM files with no whitespace between digits. + Affects: dcmpstat/apps/dcmpsprt.cc + +- Fixed annotation layout. + Affects: dcmpstat/libsrc/dviface.cc + +**** Changes from 2020.12.27 (eichelberg) + +- Fixed socket handling in dcmpsrcv. + Fixed the handling of the accepted socket in the parent process when running + dcmpsrcv on a Posix platform. The parent process did not properly close the + socket, causing the transport connection to stay open after an A-ABORT, which + in turn led to a long timeout in storescu. + Affects: dcmpstat/apps/dcmpsrcv.cc + +**** Changes from 2020.12.15 (riesmeier) + +- Fixed wrong calculation of sigmoid VOI function. + Fixed possibly wrong output of sigmoid VOI LUT function, e.g. when + processing an image with a photometric interpretation of MONOCHROME1 + (i.e. inverse). The original formula in the DICOM standard was incorrect + and has been fixed only recently with CP-1880. + Please note that the issue was only present when no presentation LUT or + display calibration was enabled (case #6 and #8 of the monochrome "VOI + SIGMOID" rendering algorithm). + Thanks to Robert Mulcahey for the report and suggested fix. + Affects: dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h + +- Introduced local constant "lowvalue" for typecast. + This is just a preparatory step for the subsequent commit. + Affects: dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h + +**** Changes from 2020.12.07 (eichelberg) + +- Fixed bug in dcmscale: + Fixed bug in dcmscale where a pointer was not checked for NULL. + This could cause a segmentation fault specifically if DCMTK was compiled + with DCMTK_ENABLE_STL and the source image contained an empty + DerivationDescription attribute. + Affects: dcmimage/apps/dcmscale.cc + +**** Changes from 2020.11.27 (riesmeier) + +- Added missing DCMTK module "dcmect". + Affects: README + README.md + +**** Changes from 2020.11.25 (riesmeier) + +- Added definition of new Storage SOP Class UID: + Updated list of Storage SOP Class UIDs known to the DCMTK based on DICOM + 2020e. This includes the Final Text version of Supplement 221 (Dermoscopy). + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + dcmnet/docs/movescu.man + dcmnet/docs/storescp.man + dcmnet/etc/storescp.cfg + dcmnet/etc/storescu.cfg + dcmqrdb/docs/dcmqrscp.man + dcmqrdb/etc/dcmqrprf.cfg + +- Updated Context Group classes for DICOM 2020e: + Updated automatically generated Context Group classes for the 2020e edition + of the DICOM standard. All supported classes were updated, even though there + were no changes to most of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2020e: + Updated automatically generated code definitions for coding schemes "DCM", + "NCIt" and "UMLS". + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + dcmsr/include/dcmtk/dcmsr/codes/umls.h + +**** Changes from 2020.11.24 (riesmeier) + +- Updated data dictionary for DICOM 2020e: + Updated data dictionary for the latest edition of the DICOM standard, + which has been released only recently. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +**** Changes from 2020.11.23 (riesmeier) + +- Removed superfluous code line: + Removed superfluous code line that could lead to namespace clashes with + other libraries, e.g. Qt. + Thanks to Adrian Schmidt-Foehre for + the report. + Affects: dcmseg/include/dcmtk/dcmseg/segtypes.h + +**** Changes from 2020.11.17 (eichelberg) + +- Fixed minor Sun Studio compiler warnings. + Affects: dcmect/tests/t_huge_concat.cc + dcmect/tests/t_roundtrip.cc + +- Added typecast required due to commit #09e11a591: + Added another typecast to logger call required due to the changes + introduced with commit #09e11a591. + Affects: dcmnet/libsrc/dulfsm.cc + +**** Changes from 2020.11.16 (eichelberg) + +- Fixed memory leak: + Fixed memory leak in SiCertificateVerifier::addUntrustedCertificateFile(). + Affects: dcmsign/libsrc/sicertvf.cc + +- Added typecast required due to commit #09e11a591: + Added typecast to logger call required due to the changes introduced + with commit #09e11a591. + Affects: dcmnet/libsrc/dulfsm.cc + +**** Changes from 2020.11.13 (eichelberg) + +- Properly quote special characters in person names: + Properly quote special characters in person names when converting DICOM + to XML using the native model (dcm2xml -nat). + This closes DCMTK issue #939. + Affects: dcmdata/libsrc/dcvrpn.cc + +- Declared finite state machine variables as volatile: + Declared the DICOM upper layer finite state machine variables as volatile. + Needed by SunPro Studio compilers when optimizing with level -xO3 or higher. + Affects: dcmnet/libsrc/dulfsm.cc + +- Disabled atof unit test related to underflow: + Disabled atof unit test that tests how underflow is handled since this + test incorrectly fails on some platforms that support denormalized + floating point numbers. + Affects: ofstd/tests/tatof.cc + +**** Changes from 2020.11.13 (riesmeier) + +- Remove unwanted files created by Doxygen: + Remove unwanted files created by Doxygen when calling "make man" + (Autoconf). This also makes sure that these files are not installed + when calling "make install". + Affects: doxygen/Makefile.in + +- Updated latest tested CMake version: + Updated information on latest CMake version that has been tested to "3.18.4". + Affects: CMake/dcmtkPrepare.cmake + +**** Changes from 2020.11.12 (riesmeier) + +- Renamed libcharls also for Autoconf build system: + Renamed libcharls (to libdcmtkcharls) also for the Autoconf build system. + See commit 46b4b4c, which made this change for the CMake build system. + Affects: dcmjpls/apps/Makefile.in + dcmjpls/libcharls/Makefile.in + dcmnet/apps/Makefile.in + +**** Changes from 2020.11.11 (eichelberg) + +- First draft of ANNOUNCE file for DCMTK 3.6.6. + Affects: ANNOUNCE + +- Updated DIMSE compatibility flag. + Affects: dcmnet/include/dcmtk/dcmnet/dul.h + +**** Changes from 2020.11.10 (eichelberg) + +- Renamed libcharls to libdcmtkcharls: + Renamed the CharLS JPEG-LS library that is built into DCMTK from + "charls" to "dcmtkcharls" to avoid a naming conflict with another + installation of the CharLS library when building shared libraries. + Thanks to Mathieu Malaterre for the suggestion + and the patch. + Affects: dcmjpls/apps/CMakeLists.txt + dcmjpls/libcharls/CMakeLists.txt + dcmjpls/libcharls/intrface.h + dcmjpls/libsrc/CMakeLists.txt + +**** Changes from 2020.11.03 (riesmeier) + +- Fixed issue with placeholders (--exec-on-eostudy): + Fixed issue with placeholders not being populated for the --exec-on-eostudy + option when receiving the first batch of images. + This issue was apparently introduced with commit 26441a226, when fixing + another issue regarding the use of --exec-on-eostudy together with --fork. + Thanks to Andreas Keizers for reporting this issue. + This closes DCMTK Bug #880. + Affects: dcmnet/apps/storescp.cc + +**** Changes from 2020.10.29 (riesmeier) + +- Output debug message on UN conversion: + Output debug message when VR of data element is reverted from "UN" to the + real value representation, e.g. when calling dcmdump or dcmconv with option + --convert-un. + Affects: dcmdata/libsrc/dcitem.cc + +**** Changes from 2020.10.20 (riesmeier) + +- Replaced "http" by "https". + Affects: README.md + +**** Changes from 2020.10.17 (riesmeier) + +- Fixed typo introduced with previous commit. + Affects: dcmnet/docs/dcmrecv.man + dcmnet/docs/echoscu.man + dcmnet/docs/findscu.man + dcmnet/docs/storescp.man + dcmnet/docs/storescu.man + dcmtls/docs/certstor.txt + dcmtls/libsrc/tlsopt.cc + +**** Changes from 2020.10.16 (eichelberg) + +- Fixed inconsistencies in man page and help text. + Affects: dcmnet/docs/dcmrecv.man + dcmnet/docs/echoscu.man + dcmnet/docs/findscu.man + dcmnet/docs/storescp.man + dcmnet/docs/storescu.man + dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmtls/docs/certstor.txt + dcmtls/libsrc/tlsopt.cc + +**** Changes from 2020.10.13 (riesmeier) + +- Increased buffer size for use of sprintf(): + Increased buffer size for use of sprintf() in order to avoid possible buffer + overflow reported by gcc 10.2.0 with option -Wformat-overflow, which is enabled + by default on Ubuntu 20.04 Linux. + Affects: dcmpstat/libsrc/dviface.cc + +**** Changes from 2020.10.07 (eichelberg) + +- Disable Fiber Local Storage on MinGW: + Disable the use of Fiber Local Storage functions on MinGW, where these + are not supported. Use Thread Local Storage instead. + Affects: oflog/include/dcmtk/oflog/thread/impl/tls.h + +**** Changes from 2020.10.06 (eichelberg) + +- Fixed incorrect static cast: + Fixed static cast that can be incorrect when compressed pixel data are handled. + Error reported by the gcc address sanitizer (-fsanitize=address). + Affects: dcmdata/libsrc/dcsequen.cc + +- Added quotes for two variables in DCMTKTargets.cmake: + The values of DCMTK_CMAKE_CXX_COMPILER and DCMTK_CMAKE_INSTALL_PREFIX + are now quoted in DCMTKTargets.cmake, in order to avoid CMake warnings + that are issued when the file is included and the path names contain + space characters (which is the default on Windows). + Affects: CMake/DCMTKConfig.cmake.in + +**** Changes from 2020.10.05 (onken) + +- Fixed optionality of Image Type atribute: + Thanks to Sergey Razuvaev for the + report. + Affects: dcmiod/libsrc/modgeneralimage.cc + +**** Changes from 2020.10.01 (schlamelcher) + +- Harmonized documentation of calcElementLength(): + The documentation of calcElementLength() is now the same for DcmObject and all + derived classes, so you will always get all the information about how the + function might behave in any case, no matter where you look. + This closes issue #857. + Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h + dcmdata/include/dcmtk/dcmdata/dcobject.h + dcmdata/include/dcmtk/dcmdata/dcpixel.h + dcmdata/include/dcmtk/dcmdata/dcsequen.h + +**** Changes from 2020.09.28 (riesmeier) + +- Updated Context Group classes for DICOM 2020d: + Updated automatically generated Context Group classes for the 2020d edition + of the DICOM standard. All supported classes were updated, even though there + were no changes to most of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2020d: + Updated automatically generated code definitions for coding scheme "DCM". + For the coding scheme "NCIt" and "UMLS", there were no changes. + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + dcmsr/include/dcmtk/dcmsr/codes/umls.h + +- Updated data dictionary for DICOM 2020d: + Updated data dictionary for the latest edition of the DICOM standard. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +**** Changes from 2020.09.25 (riesmeier) + +- Added reference to further documentation (HTML): + Added reference to further documentation on "Certification Authority (CA) + Certificate Management in DCMTK" (file "dcmtls/docs/certstor.txt"). + Affects: dcmtls/docs/certstor.txt + dcmtls/docs/dcmtls.dox + +**** Changes from 2020.09.22 (riesmeier) + +- Added new well-known Frame of Reference UIDs: + Added well-known Frame of Reference UIDs from CP-2002 (Add to well known + brain atlas frames of reference). + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + +**** Changes from 2020.09.17 (riesmeier) + +- Updated latest tested CMake version: + Updated information on latest CMake version that has been tested to "3.18.2". + Affects: CMake/dcmtkPrepare.cmake + +**** Changes from 2020.09.17 (onken) + +- Fixed access to Depths Of Scan Field attribute: + Thanks to Sergey Razuvaev for the report + and suggested fix. + Affects: dcmiod/include/dcmtk/dcmiod/modenhusimage.h + dcmiod/libsrc/modenhusimage.cc + +**** Changes from 2020.09.13 (eichelberg) + +- Fixed use-after-free error in worklist SCP: + Fixed use-after-free error in WlmActivityManager::RemoveProcessFromTable + reported by the gcc address sanitizer (-fsanitize=address). + Affects: dcmwlm/libsrc/wlmactmg.cc + +- Fixed out-of-bound read in parseSCUSCPRole(): + Fixed an out-of-bounds read access that could be caused by a malformed + A-ASSOCIATE packet. + Thanks to Matthias Gierlings + for the bug report. + This closes DCMTK issue #942. + Affects: dcmnet/libsrc/dulparse.cc + +**** Changes from 2020.09.11 (eichelberg) + +- Clean-up of dcmsign exit codes (cont'd). + Added: dcmsign/include/dcmtk/dcmsign/siexit.h + +**** Changes from 2020.09.11 (riesmeier) + +- Extended range of application-specific errors: + Extended range of application-specific / user-defined errors. Now, the + exit codes 120 to 127 also belong to this group. + Affects: ofstd/include/dcmtk/ofstd/ofexit.h + +- Fixed line indentation. + Affects: config/docs/macros.txt + dcmdata/include/dcmtk/dcmdata/dcelem.h + +**** Changes from 2020.09.11 (eichelberg) + +- Fixed typo. + Affects: config/docs/macros.txt + config/tests/arith.cc + +- Added new compile time macro DCMTK_UNDEF_SANIZITER: + Added new compile time macro DCMTK_UNDEF_SANIZITER that allows DCMTK to + be compiled with the gcc undefined behavior sanitizer (-fsanitize=undefined) + without the need to manually modify config/tests/arith.cc. + Affects: config/docs/macros.txt + config/tests/arith.cc + +- Clean-up of dcmsign exit codes: + Changed declaration file and values of dcmsign exit codes for better + consistency with the overall toolkit. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/dcsighlp.cc + +**** Changes from 2020.09.11 (riesmeier) + +- Added comments and check options in right order. + Affects: dcmwlm/apps/wlcefs.cc + +- Removed empty line. + Affects: dcmwlm/docs/wlmscpfs.man + +**** Changes from 2020.09.11 (onken) + +- Moved 2 options from processing to output section: + The following options are now in section "output" rather than + "processing": + -rfp --request-file-path [p]ath: string + path to store request files to + -rff --request-file-format [f]ormat: string (default: #t.dump) + request file name format + Affects: dcmwlm/apps/wlcefs.cc + dcmwlm/docs/wlmscpfs.man + +**** Changes from 2020.09.09 (riesmeier) + +- Fixed wrong use of doxygen markup in manpage. + Affects: dcmdata/docs/dcm2json.man + +**** Changes from 2020.09.08 (riesmeier) + +- Fixed wrong variable being read: + Fixed wrong variable being read in IODEnhUSImageModule::read(). + Thanks to Sergey Razuvaev for the report + and suggested fix. + Affects: dcmiod/libsrc/modenhusimage.cc + +- Fixed duplicate value of an error code: + With the previous commit, the existing dcmdata error code 55 was reused. + Affects: dcmdata/libsrc/dcerror.cc + +**** Changes from 2020.09.08 (eichelberg) + +- Fixed JSON InlineBinary pixel data encoding: + Implemented a new method DcmPixelData::writeJson() that properly handles + the InlineBinary JSON encoding of DICOM pixel data, which is not supported + in the DICOM JSON model for encapsulated (compressed) images. Instead of + silently writing an empty pixel data element, we now report an error. + Together with various previous commits, this closes DCMTK issue #881. + Affects: dcmdata/include/dcmtk/dcmdata/dcerror.h + dcmdata/include/dcmtk/dcmdata/dcpixel.h + dcmdata/libsrc/dcerror.cc + dcmdata/libsrc/dcpixel.cc + +- Minor fixes to dcm2json man page and help output. + Affects: dcmdata/apps/dcm2json.cc + dcmdata/docs/dcm2json.man + +**** Changes from 2020.09.03 (eichelberg) + +- Fix compilation on platforms where isinf is a macro: + Fix compilation on platforms such as OpenIndiana with STL where + isinf() and isnan() are defined as macros. + Affects: dcmdata/libsrc/dcvrfd.cc + dcmdata/libsrc/dcvrfl.cc + +**** Changes from 2020.09.02 (eichelberg) + +- Further improvements and fixes to dcm2json: + For the DS, IS, SV, and UV value representation, the decision to encode + as JSON number or string is now made for each value, not the entire + attribute. Furthermore, InlineBinary is now always encoded in little + endian byte order. + Affects: dcmdata/libsrc/dcjson.cc + dcmdata/libsrc/dcvrds.cc + dcmdata/libsrc/dcvris.cc + dcmdata/libsrc/dcvrobow.cc + dcmdata/libsrc/dcvrod.cc + dcmdata/libsrc/dcvrof.cc + dcmdata/libsrc/dcvrol.cc + dcmdata/libsrc/dcvrov.cc + dcmdata/libsrc/dcvrsv.cc + dcmdata/libsrc/dcvruv.cc + +**** Changes from 2020.09.02 (riesmeier) + +- Improved documentation of option --grayscale: + Thanks to GitHub user "malaterre" for the hint and the original patch. + Affects: dcmimage/apps/dcm2pnm.cc + dcmimage/docs/dcm2pnm.man + dcmjpeg/docs/dcmj2pnm.man + dcmjpls/docs/dcml2pnm.man + +- Added structure to documented "exit codes": + Added typical structure of DCMTK's command line tools to the documented + "exit code" of dcm2json. Also added missing exit codes to the manpage. + Affects: dcmdata/docs/dcm2json.man + +- Fixed wrong capitalization of the acronym "JSON". + Affects: dcmdata/apps/dcm2json.cc + dcmdata/docs/dcm2json.man + dcmdata/include/dcmtk/dcmdata/dcerror.h + dcmdata/include/dcmtk/dcmdata/dcjson.h + dcmdata/libsrc/dcerror.cc + dcmdata/libsrc/dcvrfd.cc + dcmdata/libsrc/dcvrfl.cc + +**** Changes from 2020.09.01 (eichelberg) + +- Various enhancements to dcm2json: + The dcm2json tool now returns well-defined error codes when terminating. + Furthermore, the handling of DICOM FL/FD elements with values that are + infinity or not a number can now be defined by a command line option. + Affects: dcmdata/apps/dcm2json.cc + dcmdata/docs/dcm2json.man + dcmdata/include/dcmtk/dcmdata/dcerror.h + dcmdata/include/dcmtk/dcmdata/dcjson.h + dcmdata/include/dcmtk/dcmdata/dcvrfd.h + dcmdata/include/dcmtk/dcmdata/dcvrfl.h + dcmdata/libsrc/dcerror.cc + dcmdata/libsrc/dcvrfd.cc + dcmdata/libsrc/dcvrfl.cc + +**** Changes from 2020.08.31 (eichelberg) + +- Fixed Json control char escaping in PN VR: + dcm2json now properly escapes control characters, quotation marks etc. + in Person Names when converting DICOM to Json. + Thanks to DCMTK forum user Shaeto for the bug report. + This closes the Json related part of DCMTK issue #939. + Affects: dcmdata/libsrc/dcvrpn.cc + +**** Changes from 2020.08.24 (riesmeier) + +- Added support for new Waveform Storage SOP Classes: + Added support for new Waveform Storage SOP Classes, introduced with + Supplement 217 (Neurophysiology Waveforms), to the DICOMDIR generation + code and to the Structured Reporting module "dcmsr". + Affects: dcmdata/libsrc/dcddirif.cc + dcmsr/include/dcmtk/dcmsr/dsrwavvl.h + dcmsr/libsrc/dsrwavvl.cc + +- Updated reference to current standard edition: + Updated reference to the current edition of the DICOM standard (2020c). + Affects: dcmsr/include/dcmtk/dcmsr/dsrimgvl.h + dcmsr/libsrc/dsrimgvl.cc + +**** Changes from 2020.08.10 (riesmeier) + +- Removed superfluous call of empty() method: + Removed superfluous call of OFVector<>::empty() method in destructor. This + makes the message "warning C4834: discarding return value of function with + 'nodiscard' attribute" reported by VisualStudio 2019 disappear. + Affects: dcmjpls/libcharls/header.cc + +**** Changes from 2020.08.06 (riesmeier) + +- Enhanced documentation of --recognize-aspect. + Affects: dcmimage/apps/dcmscale.cc + dcmimage/docs/dcmscale.man + +**** Changes from 2020.08.05 (riesmeier) + +- Added "Software" field to created TIFF images: + Added "Software" field to created TIFF images and changed first letter + of "Image Description" to upper case in order to be more consistent + with meta information of created PNG images. + Thanks to GitHub user "malaterre" for the original patch. + Affects: dcmimage/libsrc/dipitiff.cc + +**** Changes from 2020.08.03 (riesmeier) + +- Enhanced documentation of --recognize-aspect: + Enhanced documentation of the --recognize-aspect option, i.e. make clear that + it is only evaluated when actually scaling an image. + Thanks to Mathieu Malaterre for the hint. + Affects: dcmimage/apps/dcm2pnm.cc + dcmimage/docs/dcm2pnm.man + dcmjpeg/docs/dcmj2pnm.man + dcmjpls/docs/dcml2pnm.man + +**** Changes from 2020.07.31 (riesmeier) + +- Output debug information when changing the VR: + Output debug information to the logger when changing the VR to UN (or OB) + because the maximum value that can be stored in a 16-bit length field is + exceeded. + See CP-1066 and commit bb022b4 for further details. + Affects: dcmdata/libsrc/dcelem.cc + dcmdata/libsrc/dcobject.cc + +- Added basic support for leap second: + Now, a time value with 60 seconds is accepted (not only for 23:59:60). + However, calculations bases on such a time value might be incorrect. + Background: the DICOM standard explicitly allows TM and DT values to + store a value of "60" for the "SS" (seconds) component. + Affects: ofstd/include/dcmtk/ofstd/ofdatime.h + ofstd/include/dcmtk/ofstd/oftime.h + ofstd/libsrc/oftime.cc + ofstd/tests/tofdatim.cc + +**** Changes from 2020.07.29 (riesmeier) + +- Removed superfluous code line: + Removed superfluos code line to get rid of a warning reported by Visual + Studio 2019: "warning C4834: discarding return value of function with + 'nodiscard' attribute". + Affects: dcmiod/libsrc/iodmacro.cc + +**** Changes from 2020.07.28 (riesmeier) + +- Updated copyright date (where applicable): + Updated copyright date (where applicable) and added separator lines to the + text to better distinguish the individual sections. + Affects: COPYRIGHT + +**** Changes from 2020.07.27 (riesmeier) + +- Added explicit typecast to keep VS 2019 quiet: + Added explicit typecast to integer variable in order to keep VisualStudio + 2019 quiet. + Affects: dcmdata/libsrc/dcencdoc.cc + +- Made use of OFswap() in class OFFilename: + Made use of OFswap() instead of a local variable when swapping the value + of two member variables, in this case the internal representation of a + filename. + Affects: ofstd/libsrc/offile.cc + +- Enhanced support for OFpath filenames: + Enhanced support for passing an OFpath instance to the OFFilename class. + Now, the optional "convert" parameter is handled in the same way as for + other input types (such as char* or OFString). + Affects: ofstd/include/dcmtk/ofstd/offile.h + ofstd/libsrc/offile.cc + +- Fixed wrong position of a remark. + Affects: ofstd/include/dcmtk/ofstd/offile.h + +**** Changes from 2020.07.17 (riesmeier) + +- Fixed issue with invalid length of user item: + Fixed issue with an invalid value in the item-length field of the Maximum + Length Sub-Item Structure (A-ASSOCIATE-RQ). In case of a malformed + association request, the non-existent test on the item-length value could + result in a crash (segmentation fault). + Now, the value in the item-length field of this sub-item type (51h) is + checked (similar to the check for the other sub-items). + Thanks to Maria Nedyak for the bug report as well + as the test data and script that allowed for reproducing this issue. + Affects: dcmnet/libsrc/dulparse.cc + +**** Changes from 2020.07.16 (riesmeier) + +- Various fixes to API documentation. + Affects: dcmnet/libsrc/dulparse.cc + +**** Changes from 2020.07.10 (riesmeier) + +- Fixed outdated reference to default option: + Option --write-file is no longer the default in section "output file format". + Affects: dcmdata/docs/dcmconv.man + +- Removed obsolete lines from code example. + Affects: dcmjpeg/docs/dcmjpeg.dox + dcmjpls/docs/dcmjpls.dox + +- Minor fixes to manpage: + Fixed doxygen markup and typos. Also made sure that always the long version + of an option is used when referring to a command line option in the text. + Affects: dcmdata/docs/cda2dcm.man + dcmdata/docs/img2dcm.man + dcmdata/docs/pdf2dcm.man + dcmdata/docs/stl2dcm.man + +**** Changes from 2020.07.09 (arizpegomez) + +- Improved documentation of --key option: + Improved and unified the documentation of the --key option for the apps in + dcmdata. + This closes DCMTK issue #889. + Affects: .gitignore + dcmdata/docs/cda2dcm.man + dcmdata/docs/img2dcm.man + dcmdata/docs/pdf2dcm.man + dcmdata/docs/stl2dcm.man + +**** Changes from 2020.07.09 (onken) + +- New default to always re-create meta header: + The default behavior of DCMTK when writing DICOM files was to re-use + existing meta header information. This can lead to problems if essential + information in the dataset (like SOP Instance UID) changes without + explicitly enforcing those changes in the meta header, too. + By always re-creating the complete meta header it is ensured that all + its attributes are up-to-date and complete. + Affects: dcmdata/apps/dcmconv.cc + dcmdata/apps/img2dcm.cc + dcmdata/apps/mdfdsman.cc + dcmdata/docs/dcmconv.man + dcmdata/include/dcmtk/dcmdata/dcfilefo.h + dcmimage/apps/dcmquant.cc + dcmimage/apps/dcmscale.cc + dcmjpeg/apps/dcmdjpeg.cc + dcmjpls/apps/dcmdjpls.cc + dcmnet/apps/movescu.cc + +**** Changes from 2020.07.09 (schlamelcher) + +- Allow overriding support library search behaviour: + Added two new CMake cache variables to control the way DCMTK looks for + support libraries on Windows: + DCMTK_USE_FIND_PACKAGE: defaults to FALSE on Windows except MinGW + DCMTK_SUPPORT_LIBRARIES_DIR: defaults to parent of main source directory + On all other platforms, find_package() will be used as before, ignoring any + potential user choice of this setting. + Affects: CMake/3rdparty.cmake + +**** Changes from 2020.07.08 (riesmeier) + +- Updated mapping of Body Part Examined to codes: + Updated mapping of the Defined Terms for Body Part Examined (0018,0015) to + associated CID 4031 (Common Anatomic Regions) codes based on PS3.16 Table + L-1 (2020c edition of the DICOM standard). + Affects: dcmsr/libcmr/cid4031e.cc + +- Updated Context Group classes for DICOM 2020c: + Updated automatically generated Context Group classes for the 2020c edition + of the DICOM standard. All supported classes were updated, even though there + were no changes to most of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2020c: + Updated automatically generated code definitions for coding scheme "DCM". + For the coding scheme "NCIt" and "UMLS", there were no changes. + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + dcmsr/include/dcmtk/dcmsr/codes/umls.h + +- Updated data dictionary for DICOM 2020c: + Updated data dictionary for the latest edition of the DICOM standard. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +**** Changes from 2020.07.07 (eichelberg) + +- Fixed various issues in the Json output routines: + Fixed various issues in the Json output routines and the dcm2json tool: + - dcm2json -f now prints enclosing braces for the dataset, as it should. + - Fixed pretty formatting for sequences containing an empty item. + - Group length elements now omitted in Json output. + - Fixed output of IS/DS arrays larger than 4 Kbytes + - Now removing '+' characters, which are permitted in IS and DS values + in DICOM, but not in Json + - IS and DS attributes containing illegal values are now printed as string. + - UV and SV attributes are now printed as string if any value is + outside the range supported by Javascript, i.e. plus/minus 2^53-1. + Affects: dcmdata/apps/dcm2json.cc + dcmdata/include/dcmtk/dcmdata/dcdatset.h + dcmdata/include/dcmtk/dcmdata/dcfilefo.h + dcmdata/include/dcmtk/dcmdata/dcitem.h + dcmdata/include/dcmtk/dcmdata/dcvrat.h + dcmdata/include/dcmtk/dcmdata/dcvris.h + dcmdata/include/dcmtk/dcmdata/dcvrpn.h + dcmdata/include/dcmtk/dcmdata/dcvrsv.h + dcmdata/include/dcmtk/dcmdata/dcvruv.h + dcmdata/libsrc/dcdatset.cc + dcmdata/libsrc/dcfilefo.cc + dcmdata/libsrc/dcitem.cc + dcmdata/libsrc/dcjson.cc + dcmdata/libsrc/dcvrat.cc + dcmdata/libsrc/dcvrds.cc + dcmdata/libsrc/dcvris.cc + dcmdata/libsrc/dcvrsv.cc + dcmdata/libsrc/dcvruv.cc + +**** Changes from 2020.06.30 (riesmeier) + +- Fixed issue with attribute tag in JSON output: + According to PS3.18 Section F.2.2, the "name of each attribute object" + is "The eight character uppercase hexadecimal representation of a DICOM + Tag". Before, the group number was output with lowercase characters. + Thanks to DCMTK forum user "Shaeto" for the report. + Affects: dcmdata/libsrc/dcelem.cc + +- Check for data dictionary when needed for a test: + Made sure that all regression tests also work if no data dictionary is + loaded or report the test case as "failed" with an appropriate message + (if it does not work without data dictionary). + This closes DCMTK Bug #915. + Affects: dcmdata/tests/tdict.cc + dcmdata/tests/tfilter.cc + dcmdata/tests/tparser.cc + dcmdata/tests/tpath.cc + dcmdata/tests/tpread.cc + dcmdata/tests/tvrcomp.cc + dcmdata/tests/tvrdatim.cc + dcmdata/tests/tvrds.cc + dcmfg/tests/t_concatenation_loader.cc + dcmfg/tests/t_ct_acquisition_details.cc + dcmfg/tests/t_ct_acquisition_type.cc + dcmfg/tests/t_ct_image_frame_type.cc + dcmfg/tests/t_ct_position.cc + dcmfg/tests/t_ct_table_dynamics.cc + dcmfg/tests/t_deriv_image.cc + dcmfg/tests/t_frame_content.cc + dcmfg/tests/t_irradiation_event_identification.cc + dcmiod/tests/tcodes.cc + dcmnet/tests/tdump.cc + dcmseg/tests/troundtrip.cc + dcmsr/tests/tsrcmr.cc + dcmsr/tests/tsrcodvl.cc + +**** Changes from 2020.06.29 (riesmeier) + +- Reworked check on invalid Completion Flag (RDSR): + Reworked check on invalid value for Completion Flag (0040,a491) encountered + when reading or writing an X-Ray Radiation Dose Structured Report (RDSR). + However, the behavior (i.e. the output of a warning message to the logger) + should be identical to the previous implementation. + Affects: dcmsr/libsrc/dsrdoc.cc + +**** Changes from 2020.06.26 (riesmeier) + +- Added support for new Storage SOP Classes: + Added definition of new Storage SOP Class UIDs from Supplement 199 (Second + Generation Radiotherapy - RT Radiation Records) and Supplement 217 + (Neurophysiology Waveforms). + This commit also adds support for the various networking tools and for + generating a DICOMDIR referencing objects of the underlying IODs. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcddirif.cc + dcmdata/libsrc/dcuid.cc + dcmnet/docs/movescu.man + dcmnet/docs/storescp.man + dcmnet/etc/storescp.cfg + dcmnet/etc/storescu.cfg + dcmqrdb/docs/dcmqrscp.man + dcmqrdb/etc/dcmqrprf.cfg + +- Updated data dictionary for Supplement 199 + 217: + Updated data dictionary for recently approved changes to the DICOM standard, + i.e. Final Text of Supplement 199 (Second Generation Radiotherapy - RT + Radiation Records) and Supplement 217 (Neurophysiology Waveforms). + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +**** Changes from 2020.06.23 (riesmeier) + +- Output error message on missing sequence element: + Output error message on missing Verifying Observer Sequence element when + checking a DICOM file of the type "SR DOCUMENT" to be added to a DICOMDIR. + Previously, the file was rejected (e.g. by dcmgpdir or dcmmkdir) but the + reason was not given. + Thanks to DCMTK forum user "ruben.cruz" for the report and sample file. + Affects: dcmdata/libsrc/dcddirif.cc + +**** Changes from 2020.06.03 (riesmeier) + +- Added missing VRs to API documentation: + Added missing (mainly newer) VRs to API documentation of findAndGetXXX(), + putAndInsertXXX() and insertEmptyElement() methods. + Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h + +**** Changes from 2020.06.02 (riesmeier) + +- Clarified API documentation (in case of error). + Affects: dcmsr/include/dcmtk/dcmsr/dsrxmld.h + +**** Changes from 2020.05.27 (eichelberg) + +- Fixed bug in handling of pixel data representations: + Compression and decompression codecs that may modify the DICOM dataset such + that the pixel data before the coding process is not consistent anymore with + the DICOM dataset after the coding (e.g. because planar configuration or + photometric interpretation may have changed) now remove the previous + in-memory pixel data representation. + Unfortunately this requires an API change in DcmCodec::encode() and + DcmCodec::decode() that must be implemented by all image compression codecs. + Thanks to Peter Klotz for the bug report. + This closes DCMTK issue #845. + Affects: dcmdata/include/dcmtk/dcmdata/dccodec.h + dcmdata/include/dcmtk/dcmdata/dcrleccd.h + dcmdata/include/dcmtk/dcmdata/dcrlecce.h + dcmdata/libsrc/dccodec.cc + dcmdata/libsrc/dcpixel.cc + dcmdata/libsrc/dcrleccd.cc + dcmdata/libsrc/dcrlecce.cc + dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h + dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h + dcmjpeg/libsrc/djcodecd.cc + dcmjpeg/libsrc/djcodece.cc + dcmjpls/include/dcmtk/dcmjpls/djcodecd.h + dcmjpls/include/dcmtk/dcmjpls/djcodece.h + dcmjpls/libsrc/djcodecd.cc + dcmjpls/libsrc/djcodece.cc + +**** Changes from 2020.05.26 (riesmeier) + +- Fixed issue with parsing invalid meta info: + Fixed issue with an error being ignored (not propagated to the caller) + when parsing a DICOM file with an invalid meta information header. + Thanks to Maria Samoylova for the report and the + sample file. + Affects: dcmdata/libsrc/dcelem.cc + dcmdata/libsrc/dcmetinf.cc + +- Fixed name of SOP classes from Supplement 202: + Removed suffix "SOPClass" from the name of the SOP Classes introduced only + recently with Supplement 202 (Real-Time Video). The names are now consistent + with the official "UID Name" in DICOM PS3.6. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + dcmsr/libsrc/dsrtypes.cc + +- Added support for new SR IOD from Supplement 202: + Added full support for the new Rendition Selection Document IOD introduced + with Supplement 202. Please note that the associated Rendition Selection + Document Real-Time Communication SOP Class is not a Storage SOP Class, so + instances of this class are not meant to be stored as files or transferred + over the network using the Storage Service Class. + Closes DCMTK Feature #926. + Added: dcmsr/include/dcmtk/dcmsr/dsrrsdcc.h + dcmsr/libsrc/dsrrsdcc.cc + Affects: dcmsr/include/dcmtk/dcmsr/dsrtypes.h + dcmsr/libsrc/CMakeLists.txt + dcmsr/libsrc/Makefile.in + dcmsr/libsrc/dsrtypes.cc + +**** Changes from 2020.05.25 (onken) + +- Fixed doxygen and formatting. + Affects: dcmdata/include/dcmtk/dcmdata/dcpath.h + dcmdata/libsrc/dcpath.cc + +- Fixed bug that caused known private tag to be inserted with VR UN: + Thanks to forum user CStarkey for the report. + Affects: dcmdata/include/dcmtk/dcmdata/dcpath.h + dcmdata/libsrc/dcpath.cc + +**** Changes from 2020.05.22 (riesmeier) + +- Generalized support for Key Object Documents (KO): + Added more general support for SR IODs that contain the Key Object Document + Modules (on Series and Document level). This is needed since the Rendition + Selection Document IOD also contains these modules. + This is only a preparatory step for implementing support for this SR IOD + introduced with Supplement 202 (Real-Time Video). + Affects: dcmsr/include/dcmtk/dcmsr/dsrdoc.h + dcmsr/include/dcmtk/dcmsr/dsrtypes.h + dcmsr/libsrc/dsrdoc.cc + dcmsr/libsrc/dsrtypes.cc + +**** Changes from 2020.05.22 (eichelberg) + +- Changed declaration of tls_init_cleanup_func_type: + Changed declaration of tls_init_cleanup_func_type when compiling on + Win32. Required on Visual Studio 2010 when compiling with + DCMTK_LOG4CPLUS_AVOID_WIN32_FLS defined, which is needed to generate + binaries that run on Windows XP. + Thanks to Martin Czarnowski for the report. + Affects: oflog/include/dcmtk/oflog/thread/impl/tls.h + +**** Changes from 2020.05.19 (riesmeier) + +- Report an error if putElementContent() fails: + Report an error to the logger if putElementContent() fails, e.g. if the + element value to be set is invalid. + Affects: dcmdata/apps/xml2dcm.cc + +- Fixed documentation on "bulk data" in manpage: + Fixed documentation on the encoding of "bulk data" in the manpage of dcm2json. + Thanks to Mathieu Malaterre for the hint. + This closes DCMTK Bug #928. + Affects: dcmdata/docs/dcm2json.man + +**** Changes from 2020.05.18 (eichelberg) + +- Fixed comment. + Affects: ofstd/libsrc/ofstd.cc + +- Fixed HUGE_VAL constant used. + Affects: ofstd/libsrc/ofstd.cc + +**** Changes from 2020.05.18 (riesmeier) + +- Added log output on data read from file: + Added log output (on both INFO and DEBUG level) when data is read from a + binary file, e.g. for the Pixel Data element. + Affects: dcmdata/apps/dump2dcm.cc + dcmdata/apps/xml2dcm.cc + +**** Changes from 2020.05.18 (eichelberg) + +- Documented ENABLE_EXTERNAL_DICTIONARY macro. + Affects: config/docs/macros.txt + +**** Changes from 2020.05.13 (eichelberg) + +- Removed JPEG-LS option for uninterleaved encoding: + Removed the option for uninterleaved encoding (--interleave-none) from + the JPEG-LS encoder on command line and library level since this option + may in certain cases (color image with BitsStored > 12) create + compressed images that are correct but cannot be decoded by the JPEG-LS + library due to a known bug (DCMTK issue #892). The option can be + re-enabled by defining the macro ENABLE_DCMJPLS_INTERLEAVE_NONE at + compilation time. It will be re-enabled permanently once DCMTK has been + ported to CharLS 2.x, another branch of the JPEG-LS library that + requires a C++14 compiler, however. + Affects: dcmjpls/apps/dcmcjpls.cc + dcmjpls/docs/dcmcjpls.man + dcmjpls/include/dcmtk/dcmjpls/djcparam.h + dcmjpls/libsrc/djcodece.cc + +**** Changes from 2020.05.04 (riesmeier) + +- Added UID definition of UPS Query SOP Class: + Added UID definition of Unified Procedure Step - Query SOP Class introduced + with CP-1907. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + +- Added new attributes to checkMetaHeaderValue(): + Added new attributes to DcmFileFormat::checkMetaHeaderValue() that were + introduced only recently with CP-1895 (i.e. SourcePresentationAddress, + SendingPresentationAddress and ReceivingPresentationAddress). Please note, + however, that this method is currently never called for these attributes. + Affects: dcmdata/libsrc/dcfilefo.cc + +**** Changes from 2020.05.01 (eichelberg) + +- Added alternative service provision API to DcmSCP: + Added alternative service provision interface to class DcmSCP that can + be used instead of DcmSCP::listen(). The alternative interface uses two + separate calls, where the first one, openListenPort(), opens the TCP + port and executes listen(3), and the second one, acceptAssociations(), + runs the service provision code just as listen() does. The alternative + interface allows incoming network connections to be placed on the listen + backlog while the caller performs other work (such as a Storage + Commitment SCU sending out an N-ACTION-RQ) and to be accepted and + handled once acceptAssociations() is run. + Affects: dcmnet/include/dcmtk/dcmnet/scp.h + dcmnet/libsrc/scp.cc + +**** Changes from 2020.04.24 (eichelberg) + +- Added text describing the maximum UID root length. + Affects: config/docs/macros.txt + +- Fixed compiler warning in VS 2008/2010 build. + Affects: dcmfg/include/dcmtk/dcmfg/concatenationloader.h + dcmfg/libsrc/concatenationloader.cc + dcmfg/tests/t_concatenation_loader.cc + +**** Changes from 2020.04.22 (eichelberg) + +- Fixed memory leak in DcmFindSCU::performQuery(): + Fixed memory leak in DcmFindSCU::performQuery() caused by an + T_ASC_Association structure not being deleted when association + negotiation has failed. + Thanks to Matthias Gierlings + for the bug report. + Affects: dcmnet/libsrc/dfindscu.cc + +**** Changes from 2020.04.17 (riesmeier) + +- Use DIMSE-C message specific status codes: + Use DIMSE Status Codes that are specific to the respective message type, + e.g. C-FIND, C-GET, C-MOVE and C-STORE, where appropriate. + This closes DCMTK Conformance #598. + Affects: dcmnet/include/dcmtk/dcmnet/dimse.h + dcmnet/libsrc/dimdump.cc + dcmnet/libsrc/dimfind.cc + dcmnet/libsrc/dimget.cc + dcmnet/libsrc/dimmove.cc + dcmnet/libsrc/dimstore.cc + dcmnet/tests/tscusession.cc + +- Added comment on "convert" parameter (Windows): + Added missing comment to the API documentation of the constructor that the + "convert" parameter only works on Windows systems. + Affects: ofstd/include/dcmtk/ofstd/offile.h + +**** Changes from 2020.04.11 (eichelberg) + +- Fixed warnings on Sun Studio 12.6: + Renamed two methods to avoid warnings on Sun Studio 12.6. + Affects: dcmsign/include/dcmtk/dcmsign/sitsfs.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/sitsfs.cc + +**** Changes from 2020.04.10 (eichelberg) + +- Fixed dcmtls unit tests: + Fixed dcmtls unit tests in cases where OpenSSL support is disabled. + This also fixes the linker error related to libwrap on NetBSD. + Affects: dcmtls/tests/tests.cc + dcmtls/tests/tscuscptls.cc + +- Cleanup of the TLS support for DcmSCP and DcmSCPPool. + Affects: dcmnet/apps/dcmrecv.cc + dcmnet/include/dcmtk/dcmnet/scpcfg.h + dcmnet/libsrc/scp.cc + dcmnet/libsrc/scpcfg.cc + dcmnet/libsrc/scppool.cc + +**** Changes from 2020.04.09 (riesmeier) + +- Fixed various issues with new TLS support: + Made sure that the tool compiles without OpenSSL and when configured with + GNU Autioconf. Also fixed various other (minor) issues. + Affects: dcmnet/apps/Makefile.in + dcmnet/apps/dcmrecv.cc + +**** Changes from 2020.04.09 (eichelberg) + +- Replaced strncpy() with OFStandard::strlcpy(): + Replaced code that used strncpy() and manually managed the trailing zero + byte with calls to OFStandard::strlcpy(). This fixes a couple of warnings + reported by gcc -Wstringop-truncation. + Affects: dcmnet/libsrc/assoc.cc + +- Fixed minor warnings: + Fixed minor warnings reported by gcc -Wshadow. + Affects: dcmwlm/libsrc/wlfsim.cc + +- Added TLS support to dcmrecv: + Added TLS support to the DcmSCP based dcmrecv command line tool. + Affects: dcmnet/apps/CMakeLists.txt + dcmnet/apps/dcmrecv.cc + dcmnet/docs/dcmrecv.man + +- Added TLS support to DcmSCP and DcmSCPPool: + Added support for Transport Layer Security functionality to the DcmSCP + and DcmSCPPool classes. + Thanks to Michel Amat (github user amatm) and Damien Lerat for the + implementation and pull request. + Added: dcmtls/tests/CMakeLists.txt + dcmtls/tests/tests.cc + dcmtls/tests/tscuscptls.cc + Affects: dcmnet/include/dcmtk/dcmnet/scpcfg.h + dcmnet/libsrc/scp.cc + dcmnet/libsrc/scpcfg.cc + dcmnet/libsrc/scppool.cc + dcmtls/CMakeLists.txt + +**** Changes from 2020.04.07 (eichelberg) + +- Fixed Derivation Code Sequence creation: + The dcmjpeg encoder does not anymore create a derivation code sequence + when lossless compression is performed. + Thanks to Markus Sabin for the bug report + and patch. + This closes DCMTK issue #924. + Affects: dcmjpeg/libsrc/djcodece.cc + +**** Changes from 2020.04.06 (onken) + +- Try to fix VS 2008/2010 build. + Affects: dcmfg/libsrc/concatenationloader.cc + +**** Changes from 2020.04.03 (arizpegomez) + +- Added Encapsulated Document Length (CP 1851): + Included optional attribute Encapsulated Document Length to dcencdoc.cc + This closed DCMTK Conformance #877. + Affects: dcmdata/libsrc/dcencdoc.cc + +- Line spacing minor changes. + Affects: dcmdata/libsrc/dcencdoc.cc + +**** Changes from 2020.04.01 (riesmeier) + +- Updated and revised DIMSE Status Code definitions: + Updated and completely revised DIMSE Status Code definitions. Now, the + definitions and also the log output are consistent with the current + edition of the DICOM standard. Some Service Class specific DIMSE-N + Status Codes that are not needed for the DCMTK are still missing and + will be added in a future commit. + This closes DCMTK Conformance #803 and partly closes Conformance #598. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmnet/include/dcmtk/dcmnet/dimse.h + dcmnet/libsrc/dimdump.cc + dcmnet/tests/tdimse.cc + +**** Changes from 2020.03.25 (riesmeier) + +- Added missing VRs "OL" and "OV" to documentation. + Affects: dcmdata/docs/dcm2json.man + +- Added missing VR "OL" to documentation. + Affects: dcmdata/docs/dcm2xml.man + +**** Changes from 2020.03.19 (riesmeier) + +- Fixed two typos in API documentation: + Thanks to GitHub user "Raphexion" (Niklas Johansson) for the patch. + Affects: dcmpstat/include/dcmtk/dcmpstat/dvpstx.h + +**** Changes from 2020.03.15 (eichelberg) + +- Various fixes to the dcmqrscp.cfg parser: + Thanks to Jake Cobb for the bug report and patch. + Affects: dcmqrdb/libsrc/dcmqrcnf.cc + +- Fixed compilation with LibreSSL on OpenBSD 6.6. + Affects: dcmsign/libsrc/sitstamp.cc + +**** Changes from 2020.03.06 (riesmeier) + +- Added new file missing for previous commit. + Added: dcmnet/tests/tdimse.cc + Affects: dcmnet/tests/tdump.cc + +- Added macros for further DIMSE Status Classes: + Added further macros to check for certain DIMSE Status Classes (e.g. + failure). Also added macro that checks whether a DIMSE Status Code is + valid, i.e. within the range defined by the DICOM standard (see PS3.7 + Annext C). + Furthermore, all these new (and old) macros are tested in a new test case. + This partly closes DCMTK Conformance #803. + Affects: dcmnet/include/dcmtk/dcmnet/dimse.h + dcmnet/tests/CMakeLists.txt + dcmnet/tests/Makefile.in + dcmnet/tests/tdump.cc + dcmnet/tests/tests.cc + +- Fixed definition of DICOM_PENDING_STATUS macro: + According to DICOM PS3.7 Annex C, the "Pending" Status Class is defined as + Status Code "FF00 and FF01" (and not as "FFxx"). + Affects: dcmnet/include/dcmtk/dcmnet/dimse.h + +- Added missing code to DICOM_WARNING_STATUS macro: + Added missing DIMSE Status Code "0001" to the DICOM_WARNING_STATUS macro + (see PS3.7 Annex C). + Affects: dcmnet/include/dcmtk/dcmnet/dimse.h + +**** Changes from 2020.03.05 (riesmeier) + +- Fixed issues with previous commit: + Instead of "@DCMTK_CMAKE_BUILD_TYPE@" "@CMAKE_BUILD_TYPE@" should be used. + Also fixed typo in CMake variable name ("DCMTK_CMAKE_INSTALL_INLCUDEDIR") + and added missing "DCMTK_CMAKE_INSTALL_SYSCONFDIR". + Affects: CMake/DCMTKConfig.cmake.in + +**** Changes from 2020.03.03 (onken) + +- Export more build options to DCMTKConfig.cmake. + Affects: CMake/DCMTKConfig.cmake.in + +**** Changes from 2020.03.02 (eichelberg) + +- DCMTK now compiles when UNICODE/_UNICODE is defined: + DCMTK will now successfully compile when the UNICODE and _UNICODE macros + are defined on Windows. We now explicitly call the Windows API functions + that are not remapped to wide-char versions depending on the presence of + the UNICODE defines. + This closes DCMTK issue #425. + Affects: INSTALL + dcmdata/libsrc/dcencdoc.cc + dcmdata/libsrc/dcuid.cc + dcmnet/apps/storescp.cc + dcmnet/libsrc/dul.cc + dcmpstat/apps/dcmprscu.cc + dcmpstat/apps/dcmpsrcv.cc + dcmpstat/libsrc/dviface.cc + oflog/include/dcmtk/oflog/clogger.h + oflog/include/dcmtk/oflog/config.h + oflog/include/dcmtk/oflog/configrt.h + oflog/include/dcmtk/oflog/fstreams.h + oflog/include/dcmtk/oflog/helpers/property.h + oflog/include/dcmtk/oflog/socketap.h + oflog/include/dcmtk/oflog/streams.h + oflog/include/dcmtk/oflog/tchar.h + oflog/include/dcmtk/oflog/tstring.h + oflog/libsrc/config.cc + oflog/libsrc/env.cc + oflog/libsrc/fileap.cc + oflog/libsrc/fileinfo.cc + oflog/libsrc/globinit.cc + oflog/libsrc/log4judp.cc + oflog/libsrc/ntelogap.cc + oflog/libsrc/property.cc + oflog/libsrc/snprintf.cc + oflog/libsrc/sockbuff.cc + oflog/libsrc/socketap.cc + oflog/libsrc/strhelp.cc + oflog/libsrc/timehelp.cc + oflog/libsrc/winconap.cc + oflog/libsrc/windebap.cc + oflog/libsrc/winsock.cc + ofstd/include/dcmtk/ofstd/ofxml.h + ofstd/libsrc/ofstd.cc + ofstd/libsrc/oftempf.cc + ofstd/tests/tests.cc + ofstd/tests/txml.cc + +**** Changes from 2020.02.26 (eichelberg) + +- Fixed previous commit, which was incomplete. + Affects: dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdba.h + +- Fixed inconsistent forward declaration: + Fixed declaration of DcmQueryRetrieveCharacterSetOptions, which was declared + as a class in one place and as a struct in another place. + Thanks to Waldo Valenzuela for the bug report. + Affects: dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdba.h + +**** Changes from 2020.02.25 (eichelberg) + +- Improved CMake options for the WIN32 build model: + When compiling on windows, two CMake options can now be used to control the + Win32 build model (multithreaded or multithreaded DLL). When + DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS is ON, the build model can be selected + by setting DCMTK_COMPILE_WIN32_MULTITHREADED_DLL (ON for multithreaded DLL, + OFF for multithreaded). When DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS is OFF, + the DCMTK_COMPILE_WIN32_MULTITHREADED_DLL option is ignored and CMake's + default compiler options are used. + This closes DCMTK issue #903. + Affects: CMake/DCMTKConfig.cmake.in + CMake/dcmtkPrepare.cmake + INSTALL + +**** Changes from 2020.02.24 (riesmeier) + +- Added option --socket-timeout to findscu: + Added option --socket-timeout to findscu (as already done for e.g. storescu + or echoscu). Also changed the way default values of command line options are + specified (now using the same approach as for other similar tools). + This partly closed DCMTK Feature #711. + Affects: dcmnet/apps/findscu.cc + dcmnet/docs/findscu.man + +**** Changes from 2020.02.21 (eichelberg) + +- Increased buffer size to fix gcc 9.2 warning. + Affects: dcmsign/libsrc/dcsighlp.cc + +**** Changes from 2020.02.18 (riesmeier) + +- Removed escaping of "\" in Doxygen documentation. + Affects: dcmdata/docs/dcm2xml.man + dcmdata/docs/xml2dcm.man + +- Added new VRs UV, SV and OV to the documentation: + Also fixed other minor issues in the documentation of this tool. + Affects: dcmdata/apps/dump2dcm.cc + dcmdata/docs/dump2dcm.man + +**** Changes from 2020.02.14 (riesmeier) + +- Added support for new Storage SOP Classes: + Added definition of new Storage SOP Class UIDs from Supplement 176 (Second + Generation Radiotherapy - Tomotherapeutic and Robotic-Arm Treatment + Modalities) and Supplement 208 (DICOM Encapsulation of OBJ Models for 3D + Manufacturing and Virtual Reality). + This commit also adds support for the various networking tools and for + generating a DICOMDIR referencing objects of the underlying IODs. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcddirif.cc + dcmdata/libsrc/dcuid.cc + dcmnet/docs/movescu.man + dcmnet/docs/storescp.man + dcmnet/etc/storescp.cfg + dcmnet/etc/storescu.cfg + dcmqrdb/docs/dcmqrscp.man + dcmqrdb/etc/dcmqrprf.cfg + +- Added new well-known Frame of Reference UID: + Added well-known Frame of Reference UID from Supplement 176 (Second Generation + Radiotherapy - Tomotherapeutic and Robotic-Arm Treatment Modalities). + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + +**** Changes from 2020.02.13 (riesmeier) + +- Fixed issue with order of include directories: + Fixed issue with order of include directories when working with CMake on + a system where the DCMTK libraries and header files are already installed + in the same directory as one of the external support libraries (e.g. zlib + or libiconv in "/usr/local"). + Thanks to Steve Pieper for the original report and + the in-depth analysis. + Affects: CMakeLists.txt + +**** Changes from 2020.02.07 (riesmeier) + +- Output error reason to logger: + Always output the reason (e.g. called function) for an error to the logger, + not only the value of the OFCondition variable. + Also removed redundant information in case of "bad override key/path". + Affects: dcmnet/libsrc/dfindscu.cc + +**** Changes from 2020.02.04 (riesmeier) + +- Updated Context Group classes for DICOM 2020a: + Updated automatically generated Context Group classes for the 2020a edition + of the DICOM standard. All supported classes were updated, even though there + were no changes to most of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2020a: + Updated automatically generated code definitions for coding scheme "DCM" + and "NCIt". For the coding scheme "UMLS", there were no changes. + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + dcmsr/include/dcmtk/dcmsr/codes/umls.h + +**** Changes from 2020.01.31 (riesmeier) + +- Updated data dictionary for DICOM 2020a: + Updated data dictionary for the latest edition of the DICOM standard. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +- Made use of new internal VR "px" for pixel data: + Now using the new internal VR "px" for the standard Pixel Data attribute + (7fe0,0010) as well as for the private attribute (7fe1,1060), which is + created by GE Vivid S70 ultrasound systems in a non-standard conformant + manner (also for compressed pixel data, i.e. in encapsulated format). + Thanks to Marcel Claus for the report and + for providing sample objects of the GE Vivid S70. + Affects: dcmdata/data/dicom.dic + dcmdata/data/private.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +- Introduced new internal VR "px" for pixel data: + Introduced new internal value representation "px" that can be used for pixel + data, both uncompressed (OB or OW) and compressed (pixel sequence). This new + type allows for treating other attributes than (7fe0,0010) in the same way as + the Pixel Data attribute, by simply specifying the tag in the data dictionary. + In a subsequent commit, this new feature will be used for the standard Pixel + Data attribute but also for private ones. + Affects: dcmdata/apps/dump2dcm.cc + dcmdata/apps/xml2dcm.cc + dcmdata/include/dcmtk/dcmdata/dcvr.h + dcmdata/libsrc/dcitem.cc + dcmdata/libsrc/dcpixel.cc + dcmdata/libsrc/dcvr.cc + dcmdata/libsrc/dcvrpobw.cc + dcmdata/tests/telemlen.cc + dcmdata/tests/tests.cc + dcmpstat/libsrc/dvpscu.cc + +**** Changes from 2020.01.24 (onken) + +- Enhanced documentation. + Affects: dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h + +**** Changes from 2020.01.23 (riesmeier) + +- Added SOP class UIDs from Supplement 202: + Added definition of four new SOP class UIDs introduced with Supplement 202 + (Real-Time Video). + This closed DCMTK Conformance #898. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + +- Added transfer syntax UIDs from Supplement 202: + Added definition of transfer syntax UIDs from Supplement 202 (Real-Time + Video). The class DcmXfer has not been extended accordingly since the + three new transfer syntaxes (2 for video and 1 for audio) are only used + for the new "DICOM-RTV" service and not for encoding a DICOM dataset. + This partly closed DCMTK Conformance #898. + Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h + dcmdata/libsrc/dcuid.cc + +**** Changes from 2020.01.22 (onken) + +- Fixed typo in INSTALL file: + Thanks to GitHub user "iboB" for the report and fix. + Affects: INSTALL + +**** Changes from 2020.01.17 (riesmeier) + +- Fixed inappropriate warning on invalid frame time: + There are rare cases, where a frame time of 0 make sense, e.g. if the Cine + Module is required for single frame images (see PS3.3 Section C.7.6.6.1.2). + Affects: dcmimgle/libsrc/diimage.cc + +**** Changes from 2020.01.08 (riesmeier) + +- Various fixes to formatting and documentation: + Various fixes to source code formatting and Doxygen documentation of the + manpage (e.g. missing command line options and missing Doxygen markup). + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + +**** Changes from 2020.01.07 (eichelberg) + +- Added --convert-un option to dcmsign. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + +**** Changes from 2020.01.06 (onken) + +- Use typedef instead of #define for OFBool. + Affects: ofstd/include/dcmtk/ofstd/oftypes.h + +**** Changes from 2020.01.05 (riesmeier) + +- Made sure appropriate data dictionary is used: + Made sure that an appropriate DICOM data dictionary is used when performing + the test cases using "make check" (GNU Autoconf). + Affects: dcmiod/tests/Makefile.in + +- Increased buffer size for use of sprintf(): + Increased buffer size for use of sprintf() in order to avoid possible buffer + overflow reported by gcc 9.2.1 with option -Wformat-overflow, which is enabled + by default on Ubuntu 19.10 Linux. + Affects: dcmpstat/libsrc/dviface.cc + dcmpstat/libsrc/dvsighdl.cc + +- Minor fixes to source code formatting: + Fixed source code formatting (for reasons of consistency with the rest + of the file). + Affects: dcmnet/apps/storescp.cc + +**** Changes from 2020.01.05 (eichelberg) + +- Fixed bug in the parsing of UN VR sequences: + Added command line option --convert-un to storescp and fixed a bug in the + parser that caused parse errors when receiving a large sequence element with + explicit length and UN value representation, while --convert-un is active. + Thanks to Jesper Bojesen for the bug report and fix. + This closes DCMTK issue #888. + Affects: dcmdata/libsrc/dcitem.cc + dcmnet/apps/storescp.cc + dcmnet/docs/storescp.man + +**** Changes from 2020.01.02 (riesmeier) + +- Made sure appropriate data dictionary is used: + Made sure that an appropriate DICOM data dictionary is used when performing + the test cases using "make check" (GNU Autoconf). + Affects: dcmect/tests/Makefile.in + dcmfg/tests/Makefile.in + dcmseg/tests/Makefile.in + +**** Changes from 2020.01.02 (onken) + +- Force OFBool mapping to system bool type: + Drops support for systems that do not natively support the bool type. + Affects: CMake/GenerateDCMTKConfigure.cmake + CMake/osconfig.h.in + config/aclocal.m4 + config/configure + config/configure.in + config/confmod + config/include/dcmtk/config/osconfig.h.in + ofstd/include/dcmtk/ofstd/oflimits.h + ofstd/include/dcmtk/ofstd/oftraits.h + ofstd/include/dcmtk/ofstd/oftypes.h + ofstd/libsrc/Makefile.dep + +- Renamed method for consistency. + Affects: dcmdata/include/dcmtk/dcmdata/dcbytstr.h + dcmdata/libsrc/dcbytstr.cc + dcmdata/libsrc/dcvrds.cc + +- Updated autoconf dependencies. + Affects: dcmiod/tests/Makefile.dep + dcmnet/apps/Makefile.dep + dcmnet/libsrc/Makefile.dep + dcmnet/tests/Makefile.dep + dcmpstat/libsrc/Makefile.dep + dcmsign/apps/Makefile.dep + dcmsign/libsrc/Makefile.dep + dcmtls/libsrc/Makefile.dep + +- Use consistent C-FIND/GET/MOVE status codes: + DcmSCU now uses status code strings that have already been defined in + dimdump.cc in order to use consistent status strings throughout the + toolkit. + Refactored C-FIND/GET/MOVE default session handling in DcmSCU to benefit + from common code. + Added (simple, for now) test for C-FIND/MOVE session handling. + Added: dcmnet/tests/tscusession.cc + Affects: dcmnet/include/dcmtk/dcmnet/scu.h + dcmnet/libsrc/scu.cc + dcmnet/tests/CMakeLists.txt + dcmnet/tests/Makefile.in + dcmnet/tests/tests.cc + +**** Changes from 2019.12.31 (eichelberg) + +- Fixed minor bug. + Affects: dcmsign/libsrc/dcsignat.cc + +**** Changes from 2019.12.30 (eichelberg) + +- Added support for OpenSSL without Elliptic Curves: + Added support for OpenSSL libraries compiled without support for Elliptic + Curves. Needed for compiling DCMTK with the OpenSSL library shipped with + Solaris 11.3. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/siecdsa.cc + dcmsign/libsrc/siprivat.cc + dcmsign/libsrc/sitypes.cc + +**** Changes from 2019.12.30 (onken) + +- Fixed tag type for long code value support: + Make sure Code Value, Long Code Value and URN Code Value are all of type + 1C now. Fixes CP 1031 support introduced in recent commit a7ca3a60. + Affects: dcmiod/libsrc/iodmacro.cc + +- Minor formatting enhancements. + Affects: dcmiod/include/dcmtk/dcmiod/modusfor.h + dcmiod/libsrc/iodutil.cc + dcmiod/libsrc/modfloatingpointimagepixel.cc + +- Added support for long code values (CP 1301). + Added: dcmiod/tests/tcodes.cc + Affects: dcmiod/include/dcmtk/dcmiod/iodmacro.h + dcmiod/libsrc/iodmacro.cc + dcmiod/tests/CMakeLists.txt + dcmiod/tests/Makefile.in + dcmiod/tests/tests.cc + +- Fixed compiler warnings (VS 2019). + Affects: dcmect/tests/t_huge_concat.cc + dcmect/tests/t_roundtrip.cc + dcmseg/tests/troundtrip.cc + +**** Changes from 2019.12.29 (eichelberg) + +- Compatibility fixes for OpenSSL 1.0.1: + The revised dcmsign module now also compiles and works with OpenSSL 1.0.1, + the oldest OpenSSL version still supported in DCMTK. This required a rewrite + of the date/time comparison code since ASN1_TIME_diff() is not available + in OpenSSL 1.0.1. + Affects: dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/sitstamp.cc + +**** Changes from 2019.12.28 (eichelberg) + +- Fixed some minor warnings reported by VS2019. + Affects: dcmsign/libsrc/sitstamp.cc + +- Compatibility fixes for OpenSSL 1.0.2 and MSVC. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/siecdsa.cc + dcmsign/libsrc/sitstamp.cc + +**** Changes from 2019.12.27 (eichelberg) + +- Major revision of dcmsign module: + This commit completes a major revision of the dcmsign module, which adds the + following features: + - support for Elliptic Curve (ECDSA) signatures, + - support for the DICOM SR RSA Digital Signature Profile, + - support for CRLs in hashed certificate directories, + - verify chain of trust for signer certificates during signature verification, + - support for the verification of trusted timestamps, + - limited support for the creation of trusted timestamps: a timestamp + query can be generated during the signature process, but no support for the + network protocols defined in RFC 3161 is implemented yet, + - many bug fixes, improved error handling and logging. + Affects: dcmsign/docs/dcmsign.dox + +- Various improvements to dcmsign module: + Signature creation now fails with an error message if one of the tags + specified with --tag or --tag-file are not present in the dataset to + be signed. Furthermore, the digital signature purpose code is now printed + during signature verification. The 64kByte size limit for --tag-file + has been removed. + Affects: dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/dcsignat.cc + +- Improved timestamp verification code: + The timestamp verification code now performs additional consistency + checks (for example whether the timestamp was created before the start + of validity of the TSA certificate). Furthermore, a valid certified + timestamp can now extend the "lifetime" of a signature where the + signer certificate has expired, if the timestamp is still valid. + Affects: dcmsign/include/dcmtk/dcmsign/sicertvf.h + dcmsign/include/dcmtk/dcmsign/sitstamp.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/sicertvf.cc + dcmsign/libsrc/sitstamp.cc + +- Improved handling of CRLs and unsignable attributes: + Improved implementation of certificate revocation lists, which can now + also be stored in a hashed certificate directory. Improved handling and + error reporting related to unsignable attributes (such as group lengths + or UN attributes) present during signature creation of verification. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/sicertvf.h + dcmsign/include/dcmtk/dcmsign/simaccon.h + dcmsign/include/dcmtk/dcmsign/sisprof.h + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/sicertvf.cc + dcmsign/libsrc/simaccon.cc + dcmsign/libsrc/sisprof.cc + dcmsign/libsrc/sitypes.cc + +- Check unconditional attributes in signature profiles: + Signature verification now checks whether all attributes unconditionally + required to be signed are included in the signature when verifying + signatures against a signature profile. + Affects: dcmsign/include/dcmtk/dcmsign/siautopr.h + dcmsign/include/dcmtk/dcmsign/sibrsapr.h + dcmsign/include/dcmtk/dcmsign/sicreapr.h + dcmsign/include/dcmtk/dcmsign/sinullpr.h + dcmsign/include/dcmtk/dcmsign/sisprof.h + dcmsign/include/dcmtk/dcmsign/sisrpr.h + dcmsign/include/dcmtk/dcmsign/sisrvpr.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/siautopr.cc + dcmsign/libsrc/sibrsapr.cc + dcmsign/libsrc/sicreapr.cc + dcmsign/libsrc/sinullpr.cc + dcmsign/libsrc/sisprof.cc + dcmsign/libsrc/sisrpr.cc + dcmsign/libsrc/sisrvpr.cc + +- Fixed bug affecting multiple nested signatures: + Fixed bug that caused digital signatures embedded in a sequence item to be + included in the bitstream of another sequence (e.g. on main dataset level) + that signed the sequence containing this sequence item. In this case the + bitstream generated for the signature creation or verification was + not DICOM compliant. + Affects: dcmdata/libsrc/dcitem.cc + +- Check if cert was valid during signature creation: + When verifying signatures, dcmsign now checks whether the signature datetime + is within the validity period of the signer certificate. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/sitypes.cc + +- Print error message when signature is incomplete: + dcmsign now prints an error message when any of the required attributes of + the MACParametersSequence or the DigitalSignaturesSequence are absent, + empty or invalid, instead of silently ignoring such invalid signatures. + Affects: dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/sicert.cc + +- Fixed warnings reported by gcc -Wshadow. + Affects: dcmqrdb/libsrc/dcmqrdbi.cc + +- Print warning to logger when encountering weak key: + Print a warning to the logger when a weak key (RSA/DSA < 1024 bits or + ECDSA < 256 bits) is encountered in a certificate during signature + creation or verification. + Affects: dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/sicert.cc + +- Correctly print EC curve bits. + Affects: dcmpstat/libsrc/dvsighdl.cc + +- Implemented well-defined exit codes for dcmsign. + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/libsrc/dcsighlp.cc + +- Fixed memory leak in class SiCertificate. + Affects: dcmsign/libsrc/sicert.cc + +- Revised signature verification code: + Revised the signature verification code, which now checks the validity of the + signer's certificate by checking the chain of trust. Furthermore, the user can + now verify if any of the signatures present are a valid creator, authorization + or SR RSA signature. Also implemented support for adding certified timestamps + from a RFC 3161 Timestamp Response (TSR) file. When verifying a signature, + certified timestamps will now also be discovered and verified. + Added: dcmsign/include/dcmtk/dcmsign/sitsfs.h + dcmsign/libsrc/sitsfs.cc + dcmsign/libsrc/sitstamp.cc + Affects: dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h + dcmqrdb/libsrc/dcmqrcnf.cc + dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/dcsighlp.h + dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmsign/include/dcmtk/dcmsign/siautopr.h + dcmsign/include/dcmtk/dcmsign/sibrsapr.h + dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/include/dcmtk/dcmsign/sicertvf.h + dcmsign/include/dcmtk/dcmsign/sicreapr.h + dcmsign/include/dcmtk/dcmsign/sinullpr.h + dcmsign/include/dcmtk/dcmsign/sisprof.h + dcmsign/include/dcmtk/dcmsign/sisrpr.h + dcmsign/include/dcmtk/dcmsign/sitstamp.h + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/CMakeLists.txt + dcmsign/libsrc/Makefile.in + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/siautopr.cc + dcmsign/libsrc/sibrsapr.cc + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/sicertvf.cc + dcmsign/libsrc/sicreapr.cc + dcmsign/libsrc/sinullpr.cc + dcmsign/libsrc/sipurpos.cc + dcmsign/libsrc/sisrpr.cc + dcmsign/libsrc/sisrvpr.cc + dcmsign/libsrc/sitypes.cc + +- Fixed DER sequence length computation. + Affects: dcmsign/libsrc/dcsignat.cc + +- return non-zero when signature verification fails: + The dcmsign command line tool now returns a non-zero return code when one + or more of the signatures in a file have failed signature verification. + Affects: dcmsign/libsrc/dcsighlp.cc + +- Added support for SR RSA Digital Signature Profile: + Added support for the Structured Reporting RSA Digital Signature Profile + and the Digital Signature Purpose Code Sequence. Updated all signature + profile classes to include all required attributes as defined in DICOM 2019c. + Added: dcmsign/include/dcmtk/dcmsign/dcsighlp.h + dcmsign/include/dcmtk/dcmsign/sipurpos.h + dcmsign/include/dcmtk/dcmsign/sisrpr.h + dcmsign/include/dcmtk/dcmsign/sisrvpr.h + dcmsign/libsrc/dcsighlp.cc + dcmsign/libsrc/sipurpos.cc + dcmsign/libsrc/sisrpr.cc + dcmsign/libsrc/sisrvpr.cc + Affects: dcmsign/apps/dcmsign.cc + dcmsign/docs/dcmsign.man + dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmsign/include/dcmtk/dcmsign/sialgo.h + dcmsign/include/dcmtk/dcmsign/siautopr.h + dcmsign/include/dcmtk/dcmsign/sibrsapr.h + dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/include/dcmtk/dcmsign/sicertvf.h + dcmsign/include/dcmtk/dcmsign/sicreapr.h + dcmsign/include/dcmtk/dcmsign/sidsa.h + dcmsign/include/dcmtk/dcmsign/siecdsa.h + dcmsign/include/dcmtk/dcmsign/simac.h + dcmsign/include/dcmtk/dcmsign/simaccon.h + dcmsign/include/dcmtk/dcmsign/simd5.h + dcmsign/include/dcmtk/dcmsign/sinullpr.h + dcmsign/include/dcmtk/dcmsign/siprivat.h + dcmsign/include/dcmtk/dcmsign/siripemd.h + dcmsign/include/dcmtk/dcmsign/sirsa.h + dcmsign/include/dcmtk/dcmsign/sisha1.h + dcmsign/include/dcmtk/dcmsign/sisprof.h + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/CMakeLists.txt + dcmsign/libsrc/Makefile.in + dcmsign/libsrc/dcsignat.cc + dcmsign/libsrc/siautopr.cc + dcmsign/libsrc/sibrsapr.cc + dcmsign/libsrc/sicreapr.cc + dcmsign/libsrc/sinullpr.cc + dcmsign/libsrc/sisprof.cc + dcmsign/libsrc/sitypes.cc + +- Fix verification of odd-length DSA/ECDSA signatures. + Affects: dcmsign/libsrc/dcsignat.cc + +- Added initial support for ECDSA signatures. + Added: dcmsign/include/dcmtk/dcmsign/siecdsa.h + dcmsign/libsrc/siecdsa.cc + Affects: dcmsign/apps/dcmsign.cc + dcmsign/include/dcmtk/dcmsign/sicert.h + dcmsign/include/dcmtk/dcmsign/sitypes.h + dcmsign/libsrc/CMakeLists.txt + dcmsign/libsrc/Makefile.in + dcmsign/libsrc/sicert.cc + dcmsign/libsrc/siprivat.cc + +**** Changes from 2019.12.20 (eichelberg) + +- Forward trusted certificates to DcmTLSTransportLayer: + Class DcmTLSSCU did not trusted certificate files and directories set with + DcmTLSSCU::addTrustedCertFile() and DcmTLSSCU::addTrustedCertDir() to the + underlying DcmTLSTransportLayer instance. This fix was developed by + Michael Onken already in 2017, but apparently never committed. + Affects: dcmtls/libsrc/tlsscu.cc + +**** Changes from 2019.12.17 (onken) + +- Fixed compiler warning (shadowed variable). + Affects: dcmseg/tests/troundtrip.cc + +**** Changes from 2019.12.12 (onken) + +- Fix OFtuple-based compile error in VS 2008/2010: + Try to fix OFtuple-based compile error in VS 2008/2010, and address + compiler warning in SunPro Studio 12.6 about possible NULL pointer + reference. + Affects: dcmect/tests/t_huge_concat.cc + dcmfg/libsrc/concatenationloader.cc + +**** Changes from 2019.12.11 (riesmeier) + +- Fixed warning reported by gcc (-Wsign-compare). + Affects: ofstd/tests/tmap.cc + +**** Changes from 2019.12.11 (onken) + +- Fixed more compiler warnings. + Affects: dcmdata/libi2d/i2djpgs.cc + dcmfg/libsrc/concatenationloader.cc + dcmseg/libsrc/segdoc.cc + dcmtract/libsrc/trctrack.cc + +- Fixed compiler warning. + Affects: dcmfg/libsrc/fgbase.cc + +- Fixed/completed doxygen documentation. + Affects: dcmdata/include/dcmtk/dcmdata/dcvrds.h + dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h + dcmtract/include/dcmtk/dcmtract/trcmeasurement.h + dcmtract/include/dcmtk/dcmtract/trcmodtractresults.h + dcmtract/include/dcmtk/dcmtract/trcstatistic.h + dcmtract/include/dcmtk/dcmtract/trctrack.h + dcmtract/include/dcmtk/dcmtract/trctrackset.h + +- Removed accidentially commited configure file. + Removed: configure + +- Use constants instead of magic numbers. + Affects: dcmfg/include/dcmtk/dcmfg/concatenationcreator.h + dcmfg/libsrc/concatenationcreator.cc + +- Fixed data types and compiler warnings: + Fixed data types used in Concatenation code (e.g. maximum number of + frames per instance, maximum number of concatenation instances). + Fixed compiler warnings, especially those from integer conversions. + Adapted documentation where necessary. + Affects: dcmect/libsrc/enhanced_ct.cc + dcmfg/include/dcmtk/dcmfg/concatenationcreator.h + dcmfg/include/dcmtk/dcmfg/concatenationloader.h + dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h + dcmfg/include/dcmtk/dcmfg/fgfracon.h + dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h + dcmfg/include/dcmtk/dcmfg/fgpixmsr.h + dcmfg/libsrc/concatenationcreator.cc + dcmfg/libsrc/concatenationloader.cc + dcmfg/libsrc/fgbase.cc + dcmfg/libsrc/fgctadditionalxraysource.cc + dcmfg/libsrc/fgfracon.cc + dcmfg/libsrc/fgimagedatatype.cc + dcmfg/libsrc/fgpixmsr.cc + dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h + dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h + dcmiod/include/dcmtk/dcmiod/modimagepixel.h + dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h + dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h + dcmiod/include/dcmtk/dcmiod/modusfor.h + dcmiod/libsrc/iodcontentitemmacro.cc + dcmiod/libsrc/iodutil.cc + dcmiod/libsrc/modfloatingpointimagepixel.cc + dcmiod/libsrc/modimagepixel.cc + dcmiod/libsrc/modimagepixelbase.cc + dcmiod/libsrc/modusfor.cc + ofstd/include/dcmtk/ofstd/oftest.h + +- Fix recusion (call base class version instead). + Affects: dcmect/include/dcmtk/dcmect/enhanced_ct.h + +- Fixed nested angle brackets and other formatting: + Fixed nested closing angle brackets ("> >") for templates that require a + space in C++03. + Made formatting more consistent. + Affects: dcmect/include/dcmtk/dcmect/enhanced_ct.h + dcmect/libsrc/enhanced_ct.cc + dcmect/tests/t_huge_concat.cc + dcmect/tests/t_roundtrip.cc + dcmfg/include/dcmtk/dcmfg/concatenationloader.h + dcmfg/libsrc/fgderimg.cc + dcmiod/include/dcmtk/dcmiod/iodimage.h + dcmiod/include/dcmtk/dcmiod/iodutil.h + dcmiod/libsrc/iodcommn.cc + dcmiod/libsrc/iodcontentitemmacro.cc + dcmiod/libsrc/iodmacro.cc + dcmiod/libsrc/iodreferences.cc + dcmiod/libsrc/iodrules.cc + dcmiod/libsrc/iodutil.cc + dcmiod/libsrc/modacquisitioncontext.cc + dcmiod/libsrc/modbase.cc + dcmiod/libsrc/modcommoninstanceref.cc + dcmiod/libsrc/modenhequipment.cc + dcmiod/libsrc/modenhusimage.cc + dcmiod/libsrc/modenhusseries.cc + dcmiod/libsrc/modequipment.cc + dcmiod/libsrc/modfloatingpointimagepixel.cc + dcmiod/libsrc/modfor.cc + dcmiod/libsrc/modgeneralimage.cc + dcmiod/libsrc/modgeneralseries.cc + dcmiod/libsrc/modgeneralstudy.cc + dcmiod/libsrc/modhelp.cc + dcmiod/libsrc/modimagepixel.cc + dcmiod/libsrc/modimagepixelbase.cc + dcmiod/libsrc/modmultiframedimension.cc + dcmiod/libsrc/modmultiframefg.cc + dcmiod/libsrc/modpatient.cc + dcmiod/libsrc/modpatientstudy.cc + dcmiod/libsrc/modsegmentationseries.cc + dcmiod/libsrc/modsopcommon.cc + dcmiod/libsrc/modsynchronization.cc + dcmiod/libsrc/modusfor.cc + dcmiod/tests/timagepixel.cc + dcmseg/include/dcmtk/dcmseg/segdoc.h + dcmseg/libsrc/segdoc.cc + dcmseg/libsrc/segtypes.cc + dcmseg/tests/tconcat_binary.cc + +**** Changes from 2019.12.10 (onken) + +- New module dcmect for working with Enhanced CT: + Added new DCMTK module dcmect which facilitates creation, loading, + (partly) modification and storing Enhanced CT objects. + Also included is a general Concatenation API that allows to create and + re-assemble Concatenations from given DICOM datasets. The related + classes are called ConcatenationCreator and ConcatentionLoader and are + part of the dcmfg module. Right now, only uncompressed ("unencapsulated") + pixel data is supported. + The existing Segmentation API (dcmseg) as well as the new Enhanced CT API + (dcmect) both support writing and reading Concatenations via dedicated + methods. + Acknowledgement: Thanks to GE Aviation for sponsoring this feature. + Added: configure + dcmect/CMakeLists.txt + dcmect/Makefile.in + dcmect/configure + dcmect/data/Makefile.in + dcmect/docs/Makefile.in + dcmect/docs/dcmect.dox + dcmect/etc/Makefile.in + dcmect/include/CMakeLists.txt + dcmect/include/Makefile.in + dcmect/include/dcmtk/dcmect/def.h + dcmect/include/dcmtk/dcmect/enhanced_ct.h + dcmect/include/dcmtk/dcmect/types.h + dcmect/libsrc/CMakeLists.txt + dcmect/libsrc/Makefile.dep + dcmect/libsrc/Makefile.in + dcmect/libsrc/enhanced_ct.cc + dcmect/libsrc/types.cc + dcmect/tests/CMakeLists.txt + dcmect/tests/Makefile.dep + dcmect/tests/Makefile.in + dcmect/tests/t_huge_concat.cc + dcmect/tests/t_roundtrip.cc + dcmect/tests/tests.cc + dcmfg/include/dcmtk/dcmfg/concatenationcreator.h + dcmfg/include/dcmtk/dcmfg/concatenationloader.h + dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h + dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h + dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h + dcmfg/include/dcmtk/dcmfg/fgctexposure.h + dcmfg/include/dcmtk/dcmfg/fgctgeometry.h + dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h + dcmfg/include/dcmtk/dcmfg/fgctposition.h + dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h + dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h + dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h + dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h + dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h + dcmfg/libsrc/concatenationcreator.cc + dcmfg/libsrc/concatenationloader.cc + dcmfg/libsrc/fgctacquisitiondetails.cc + dcmfg/libsrc/fgctacquisitiontype.cc + dcmfg/libsrc/fgctadditionalxraysource.cc + dcmfg/libsrc/fgctexposure.cc + dcmfg/libsrc/fgctgeometry.cc + dcmfg/libsrc/fgctimageframetype.cc + dcmfg/libsrc/fgctposition.cc + dcmfg/libsrc/fgctreconstruction.cc + dcmfg/libsrc/fgcttabledynamics.cc + dcmfg/libsrc/fgctxraydetails.cc + dcmfg/libsrc/fgirradiationeventid.cc + dcmfg/libsrc/fgtemporalposition.cc + dcmfg/tests/t_concatenation_creator.cc + dcmfg/tests/t_concatenation_loader.cc + dcmfg/tests/t_ct_acquisition_details.cc + dcmfg/tests/t_ct_acquisition_type.cc + dcmfg/tests/t_ct_image_frame_type.cc + dcmfg/tests/t_ct_position.cc + dcmfg/tests/t_ct_table_dynamics.cc + dcmfg/tests/t_irradiation_event_identification.cc + dcmseg/tests/tconcat_binary.cc + dcmseg/tests/troundtrip.cc + Affects: CMakeLists.txt + Makefile + config/modules + config/tests/stack.cc + dcmdata/include/dcmtk/dcmdata/dcbytstr.h + dcmdata/include/dcmtk/dcmdata/dcerror.h + dcmdata/include/dcmtk/dcmdata/dcitem.h + dcmdata/include/dcmtk/dcmdata/dcvrds.h + dcmdata/libsrc/dcbytstr.cc + dcmdata/libsrc/dcitem.cc + dcmdata/libsrc/dcvrds.cc + dcmdata/tests/Makefile.dep + dcmdata/tests/tests.cc + dcmdata/tests/tvrds.cc + dcmfg/include/dcmtk/dcmfg/fg.h + dcmfg/include/dcmtk/dcmfg/fgbase.h + dcmfg/include/dcmtk/dcmfg/fgdefine.h + dcmfg/include/dcmtk/dcmfg/fgderimg.h + dcmfg/include/dcmtk/dcmfg/fgfact.h + dcmfg/include/dcmtk/dcmfg/fgfracon.h + dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h + dcmfg/include/dcmtk/dcmfg/fgframevoilut.h + dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h + dcmfg/include/dcmtk/dcmfg/fginterface.h + dcmfg/include/dcmtk/dcmfg/fgparametricmapframetype.h + dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h + dcmfg/include/dcmtk/dcmfg/fgpixmsr.h + dcmfg/include/dcmtk/dcmfg/fgplanor.h + dcmfg/include/dcmtk/dcmfg/fgplanorvol.h + dcmfg/include/dcmtk/dcmfg/fgplanpo.h + dcmfg/include/dcmtk/dcmfg/fgplanposvol.h + dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h + dcmfg/include/dcmtk/dcmfg/fgseg.h + dcmfg/include/dcmtk/dcmfg/fgtypes.h + dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h + dcmfg/include/dcmtk/dcmfg/stack.h + dcmfg/include/dcmtk/dcmfg/stackinterface.h + dcmfg/libsrc/CMakeLists.txt + dcmfg/libsrc/Makefile.dep + dcmfg/libsrc/Makefile.in + dcmfg/libsrc/fg.cc + dcmfg/libsrc/fgbase.cc + dcmfg/libsrc/fgderimg.cc + dcmfg/libsrc/fgfact.cc + dcmfg/libsrc/fgfracon.cc + dcmfg/libsrc/fgframeanatomy.cc + dcmfg/libsrc/fgframevoilut.cc + dcmfg/libsrc/fgimagedatatype.cc + dcmfg/libsrc/fginterface.cc + dcmfg/libsrc/fgparametricmapframetype.cc + dcmfg/libsrc/fgpixeltransform.cc + dcmfg/libsrc/fgpixmsr.cc + dcmfg/libsrc/fgplanor.cc + dcmfg/libsrc/fgplanorvol.cc + dcmfg/libsrc/fgplanpo.cc + dcmfg/libsrc/fgplanposvol.cc + dcmfg/libsrc/fgrealworldvaluemapping.cc + dcmfg/libsrc/fgseg.cc + dcmfg/libsrc/fgtypes.cc + dcmfg/libsrc/fgusimagedescription.cc + dcmfg/libsrc/stack.cc + dcmfg/libsrc/stackinterface.cc + dcmfg/tests/CMakeLists.txt + dcmfg/tests/Makefile.dep + dcmfg/tests/Makefile.in + dcmfg/tests/t_deriv_image.cc + dcmfg/tests/t_frame_content.cc + dcmfg/tests/tests.cc + dcmiod/include/dcmtk/dcmiod/cielabutil.h + dcmiod/include/dcmtk/dcmiod/iodcommn.h + dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h + dcmiod/include/dcmtk/dcmiod/ioddef.h + dcmiod/include/dcmtk/dcmiod/iodimage.h + dcmiod/include/dcmtk/dcmiod/iodmacro.h + dcmiod/include/dcmtk/dcmiod/iodreferences.h + dcmiod/include/dcmtk/dcmiod/iodrules.h + dcmiod/include/dcmtk/dcmiod/iodtypes.h + dcmiod/include/dcmtk/dcmiod/iodutil.h + dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h + dcmiod/include/dcmtk/dcmiod/modbase.h + dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h + dcmiod/include/dcmtk/dcmiod/modenhequipment.h + dcmiod/include/dcmtk/dcmiod/modenhusimage.h + dcmiod/include/dcmtk/dcmiod/modenhusseries.h + dcmiod/include/dcmtk/dcmiod/modequipment.h + dcmiod/include/dcmtk/dcmiod/modfloatingpointimagepixel.h + dcmiod/include/dcmtk/dcmiod/modfor.h + dcmiod/include/dcmtk/dcmiod/modgeneralimage.h + dcmiod/include/dcmtk/dcmiod/modgeneralseries.h + dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h + dcmiod/include/dcmtk/dcmiod/modhelp.h + dcmiod/include/dcmtk/dcmiod/modimagepixel.h + dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h + dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h + dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h + dcmiod/include/dcmtk/dcmiod/modmultiframefg.h + dcmiod/include/dcmtk/dcmiod/modpatient.h + dcmiod/include/dcmtk/dcmiod/modpatientstudy.h + dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h + dcmiod/include/dcmtk/dcmiod/modsopcommon.h + dcmiod/include/dcmtk/dcmiod/modsynchronisation.h + dcmiod/include/dcmtk/dcmiod/modusfor.h + dcmiod/libsrc/Makefile.dep + dcmiod/libsrc/cielabutil.cc + dcmiod/libsrc/iodcommn.cc + dcmiod/libsrc/iodcontentitemmacro.cc + dcmiod/libsrc/iodmacro.cc + dcmiod/libsrc/iodreferences.cc + dcmiod/libsrc/iodrules.cc + dcmiod/libsrc/iodtypes.cc + dcmiod/libsrc/iodutil.cc + dcmiod/libsrc/modacquisitioncontext.cc + dcmiod/libsrc/modbase.cc + dcmiod/libsrc/modcommoninstanceref.cc + dcmiod/libsrc/modenhequipment.cc + dcmiod/libsrc/modenhusimage.cc + dcmiod/libsrc/modenhusseries.cc + dcmiod/libsrc/modequipment.cc + dcmiod/libsrc/modfloatingpointimagepixel.cc + dcmiod/libsrc/modfor.cc + dcmiod/libsrc/modgeneralimage.cc + dcmiod/libsrc/modgeneralseries.cc + dcmiod/libsrc/modgeneralstudy.cc + dcmiod/libsrc/modhelp.cc + dcmiod/libsrc/modimagepixel.cc + dcmiod/libsrc/modimagepixelbase.cc + dcmiod/libsrc/modmultiframedimension.cc + dcmiod/libsrc/modmultiframefg.cc + dcmiod/libsrc/modpatient.cc + dcmiod/libsrc/modpatientstudy.cc + dcmiod/libsrc/modsegmentationseries.cc + dcmiod/libsrc/modsopcommon.cc + dcmiod/libsrc/modsynchronization.cc + dcmiod/libsrc/modusfor.cc + dcmiod/tests/Makefile.dep + dcmiod/tests/tcielabutil.cc + dcmiod/tests/timagepixel.cc + dcmpmap/libsrc/Makefile.dep + dcmpmap/libsrc/dpmparametricmapiod.cc + dcmseg/include/dcmtk/dcmseg/segdef.h + dcmseg/include/dcmtk/dcmseg/segdoc.h + dcmseg/include/dcmtk/dcmseg/segment.h + dcmseg/include/dcmtk/dcmseg/segtypes.h + dcmseg/include/dcmtk/dcmseg/segutils.h + dcmseg/libsrc/Makefile.dep + dcmseg/libsrc/segdoc.cc + dcmseg/libsrc/segment.cc + dcmseg/libsrc/segtypes.cc + dcmseg/libsrc/segutils.cc + dcmseg/tests/CMakeLists.txt + dcmseg/tests/Makefile.dep + dcmseg/tests/Makefile.in + dcmseg/tests/tests.cc + dcmseg/tests/tutils.cc + dcmtract/libsrc/Makefile.dep + doxygen/htmldocs.dox + ofstd/include/dcmtk/ofstd/ofmap.h + ofstd/tests/tmap.cc + +**** Changes from 2019.12.10 (schlamelcher) + +- Fixed various typos and whitespace errors: + Thanks to Peter Klotz for the suggested patch. + Affects: dcmdata/apps/mdfdsman.cc + dcmdata/data/SC.dump + dcmdata/data/VLP.dump + dcmdata/include/dcmtk/dcmdata/dcelem.h + dcmdata/libsrc/dcswap.cc + dcmimage/include/dcmtk/dcmimage/diqthash.h + dcmnet/include/dcmtk/dcmnet/diutil.h + dcmnet/include/dcmtk/dcmnet/scp.h + dcmnet/include/dcmtk/dcmnet/scu.h + dcmnet/libsrc/dimfind.cc + dcmnet/libsrc/dimget.cc + dcmpstat/apps/dcmprscu.cc + dcmpstat/apps/dcmpsrcv.cc + dcmqrdb/libsrc/dcmqrdbi.cc + dcmrt/include/dcmtk/dcmrt/drmdose.h + dcmsign/include/dcmtk/dcmsign/dcsignat.h + dcmwlm/libsrc/wldsfs.cc + docs/CHANGES.320 + docs/CHANGES.342 + docs/CHANGES.350 + docs/CHANGES.352 + docs/CHANGES.360 + docs/CHANGES.362 + docs/CHANGES.363 + oflog/include/dcmtk/oflog/helpers/queue.h + oflog/libsrc/filter.cc + oflog/libsrc/timehelp.cc + +**** Changes from 2019.11.28 (riesmeier) + +- Do not install "dummy" CHANGES file: + Do not install the "dummy" CHANGES file from the main directory of the + source tree since it does not contain any useful information (after the + DCMTK has been installed). + Affects: CHANGES + CMakeLists.txt + Makefile + config/rootconf + +**** Changes from 2019.11.26 (riesmeier) + +- Added new option --limit-output to findscu: + Added new option to findscu and the underlying C++ classes that allows for + specifying the maximum number of responses written to file. Limiting the + number of responses written to file might be useful e.g. if the C-FIND-CANCEL + request does not prevent the SCP from sending further C-FIND-RSP messages. + Affects: dcmnet/apps/findscu.cc + dcmnet/docs/findscu.man + dcmnet/include/dcmtk/dcmnet/dfindscu.h + dcmnet/libsrc/dfindscu.cc + +**** Changes from 2019.11.20 (riesmeier) + +- Updated Context Group classes for DICOM 2019e: + Updated automatically generated Context Group classes for the 2019e edition + of the DICOM standard. All supported classes were updated, even though there + were not changes to all of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2019e: + Updated automatically generated code definitions for coding scheme "DCM" + and "UMLS". For the coding scheme "NCIt", there were no changes. + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + dcmsr/include/dcmtk/dcmsr/codes/umls.h + +**** Changes from 2019.11.19 (riesmeier) + +- Updated data dictionary for DICOM 2019e: + Updated data dictionary for the latest edition of the DICOM standard. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + +**** Changes from 2019.11.19 (onken) + +- Clarified documentation for dcmodify: + Thanks to forum user "JustSomeGuy" for the report. + Affects: dcmdata/docs/dcmodify.man + +**** Changes from 2019.11.15 (riesmeier) + +- Implemented support for CP-1913 (FT): + Implemented support for CP-1913 "Coding Scheme Version requires Coding Scheme + Designator to be present", i.e. enhanced the checks in DSRCodedEntryValue. + Also added a new test case that explicitly checks for this combination. + Affects: dcmsr/libsrc/dsrcodvl.cc + dcmsr/tests/tsrcodvl.cc + +- Implemented support for CP-1893 (FT): + Implemented support for CP-1893 "Fix inconsistent Relationship Content + Constraints (SR IODs from Supplement 164)", i.e. removed Target Value Type + "TIME" from Relationship Content Constraints for Planned Imaging Agent + Administration SR IOD and Performed Imaging Agent Administration SR IOD. + Affects: dcmsr/libsrc/dsrpficc.cc + dcmsr/libsrc/dsrplicc.cc + +**** Changes from 2019.11.08 (riesmeier) + +- Fixed possible issue with getFullOverlayData(): + Fixed issue with getFullOverlayData() that could cause a crash (segmentation + fault) when processing an overlay plane with an origin other than (0,0). + Note that the dcm2pnm/dcmj2pnm/dcml2pnm command line tool does not use this + method and is, therefore, not affected by this issue. + This closes DCMTK Bug #911. + Thanks to Bartosz Bialoskorski for the report + and the sample DICOM file. + Affects: dcmimgle/include/dcmtk/dcmimgle/diovpln.h + dcmimgle/libsrc/diovlay.cc + dcmimgle/libsrc/diovpln.cc + +**** Changes from 2019.10.31 (riesmeier) + +- Updated Context Group classes for DICOM 2019d: + Updated automatically generated Context Group classes for the 2019d edition + of the DICOM standard. All supported classes were updated, even though there + were not changes to all of them. + Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h + dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h + dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h + dcmsr/libcmr/cid100.cc + dcmsr/libcmr/cid10013.cc + dcmsr/libcmr/cid10033.cc + dcmsr/libcmr/cid11.cc + dcmsr/libcmr/cid244.cc + dcmsr/libcmr/cid29.cc + dcmsr/libcmr/cid4020.cc + dcmsr/libcmr/cid4021.cc + dcmsr/libcmr/cid4031.cc + dcmsr/libcmr/cid42.cc + dcmsr/libcmr/cid6147.cc + dcmsr/libcmr/cid7021.cc + dcmsr/libcmr/cid7181.cc + dcmsr/libcmr/cid7445.cc + dcmsr/libcmr/cid7452.cc + dcmsr/libcmr/cid7453.cc + dcmsr/libcmr/cid7464.cc + dcmsr/libcmr/cid7469.cc + +- Updated code definitions for DICOM 2019d: + Updated automatically generated code definitions for coding scheme "DCM" + and "NCIt". For the coding scheme "UMLS", there were no changes. + Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h + dcmsr/include/dcmtk/dcmsr/codes/ncit.h + +- Updated data dictionary for DICOM 2019d: + Updated data dictionary for the latest edition of the DICOM standard. + Affects: dcmdata/data/dicom.dic + dcmdata/include/dcmtk/dcmdata/dcdeftag.h + dcmdata/libsrc/dcdictbi.cc + dcmrt/libsrc/drtrbs4.cc + dcmrt/libsrc/drtrbs8.cc + +**** Changes from 2019.10.29 (riesmeier) + +- Enhanced performance of getting a sequence item: + Significantly enhanced performance of getting an item from the end of a + DcmSequenceOfItems or DcmPixelSequence instance. These enhancements are + based on an improved version of the DcmList::seek_to() method. + Affects: dcmdata/libsrc/dclist.cc + dcmdata/tests/tsequen.cc + +- Enhanced performance of inserting sequence items: + Significantly enhanced the performance of inserting items at the end of a + DcmSequenceOfItems or DcmPixelSequence instance. These enhancements are + based on a smarter use of the underlying DcmList class. + Adding 99,999 items to a pixel sequence now only takes a fraction of a + second compared to a very large number of seconds (as it was before). + Also clarified that the item-related helper methods in the DcmItem class, + such as findAndGetSequenceItem(), cannot be used with an instance of the + DcmPixelItem class (since this class is not derived from DcmItem). + Added: dcmdata/tests/tsequen.cc + Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h + dcmdata/libsrc/dcitem.cc + dcmdata/libsrc/dcpixseq.cc + dcmdata/libsrc/dcsequen.cc + dcmdata/tests/CMakeLists.txt + dcmdata/tests/Makefile.in + dcmdata/tests/tests.cc + +- Fixed typos and other minor issues. + Affects: INSTALL + ofstd/libsrc/ofstring.cc + +**** Changes from 2019.10.29 (schlamelcher) + +- Updated version information for 3.6.5+ development: + Updated version information marking the start of DCMTK development post minor + release 3.6.5. + Moved official ANNOUNCE file of the DCMTK release 3.6.5 to the "docs" + subfolder and replaced the main ANNOUNCE file with a "dummy". + Added: docs/ANNOUNCE.365 + Affects: ANNOUNCE + CMake/dcmtkPrepare.cmake + VERSION + config/configure + config/configure.in diff --git a/doxygen/Makefile.in b/doxygen/Makefile.in index d39904b2..41c349a0 100644 --- a/doxygen/Makefile.in +++ b/doxygen/Makefile.in @@ -31,6 +31,7 @@ man: manpages.cfg > manpages.tmp $(DOXYGEN) manpages.tmp rm -f manpages/man1/*.man.1 + rm -f manpages/man1/_*_.1 ./patchman.sh text: diff --git a/doxygen/htmldocs.dox b/doxygen/htmldocs.dox index b4ecff75..427e3ac3 100644 --- a/doxygen/htmldocs.dox +++ b/doxygen/htmldocs.dox @@ -10,6 +10,7 @@ DCMTK contains the following sub-packages, each in its own sub-directory: \li \ref mod_config \li \ref mod_dcmdata +\li \ref mod_dcmect \li \ref mod_dcmfg \li \ref mod_dcmimage \li \ref mod_dcmimgle diff --git a/doxygen/manpages/man1/cda2dcm.1 b/doxygen/manpages/man1/cda2dcm.1 index 757eb275..92985e99 100644 --- a/doxygen/manpages/man1/cda2dcm.1 +++ b/doxygen/manpages/man1/cda2dcm.1 @@ -1,4 +1,4 @@ -.TH "cda2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "cda2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME cda2dcm \- Encapsulate CDA file into DICOM file format @@ -169,6 +169,31 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes .fi .PP +.SH "NOTES" +.PP +.SS "Attribute Sources" +The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information: +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be used to add further attributes to the DICOM output file\&. +.PP +.PD 0 +.IP "\(bu" 2 +It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&. +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be present more than once\&. +.PP +.PD 0 +.IP "\(bu" 2 +The value part (after the '=') may be absent causing the attribute to be set with zero length\&. +.PP +.PD 0 +.IP "\(bu" 2 +Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&. +.PP .SH "LOGGING" .PP The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&. @@ -213,4 +238,4 @@ The \fBcda2dcm\fP utility will attempt to load DICOM data dictionaries specified The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 2018 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2018-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcm2json.1 b/doxygen/manpages/man1/dcm2json.1 index 36599b10..e59f3447 100644 --- a/doxygen/manpages/man1/dcm2json.1 +++ b/doxygen/manpages/man1/dcm2json.1 @@ -1,4 +1,4 @@ -.TH "dcm2json" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcm2json" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcm2json \- Convert DICOM file and data set to JSON @@ -14,7 +14,7 @@ dcm2json [options] dcmfile-in [jsonfile-out] .PP The \fBdcm2json\fP utility converts the contents of a DICOM file (file format or raw data set) to JSON (JavaScript Object Notation)\&. The output refers to the 'DICOM JSON Model', which is found in DICOM Part 18 Section F\&. .PP -If \fBdcm2json\fP reads a raw data set (DICOM data without a file format meta-header) it will attempt to guess the transfer syntax by examining the first few bytes of the file\&. It is not always possible to correctly guess the transfer syntax and it is better to convert a data set to a file format whenever possible (using the \fBdcmconv\fP utility)\&. It is also possible to use the \fI-f\fP and \fI-t[ieb]\fP options to force \fBdcm2json\fP to read a data set with a particular transfer syntax\&. +If \fBdcm2json\fP reads a raw data set (DICOM data without a file format meta-header), it will attempt to guess the transfer syntax by examining the first few bytes of the file\&. It is not always possible to correctly guess the transfer syntax and it is better to convert a data set to a file format whenever possible (using the \fBdcmconv\fP utility)\&. It is also possible to use the \fI-f\fP and \fI-t[ieb]\fP options to force \fBdcm2json\fP to read a data set with a particular transfer syntax\&. .SH "PARAMETERS" .PP .PP @@ -29,30 +29,30 @@ jsonfile-out JSON output filename (default: stdout) .SS "general options" .PP .nf - -h --help - print this help text and exit + -h --help + print this help text and exit - --version - print version information and exit + --version + print version information and exit - --arguments - print expanded command line arguments + --arguments + print expanded command line arguments - -q --quiet - quiet mode, print no warnings and errors + -q --quiet + quiet mode, print no warnings and errors - -v --verbose - verbose mode, print processing details + -v --verbose + verbose mode, print processing details - -d --debug - debug mode, print debug information + -d --debug + debug mode, print debug information - -ll --log-level [l]evel: string constant - (fatal, error, warn, info, debug, trace) - use level l for the logger + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger - -lc --log-config [f]ilename: string - use config file f for the logger + -lc --log-config [f]ilename: string + use config file f for the logger .fi .PP .SS "input options" @@ -60,31 +60,42 @@ jsonfile-out JSON output filename (default: stdout) .nf input file format: - +f --read-file - read file format or data set (default) + +f --read-file + read file format or data set (default) - +fo --read-file-only - read file format only + +fo --read-file-only + read file format only - -f --read-dataset - read data set without file meta information + -f --read-dataset + read data set without file meta information input transfer syntax: - -t= --read-xfer-auto - use TS recognition (default) + -t= --read-xfer-auto + use TS recognition (default) - -td --read-xfer-detect - ignore TS specified in the file meta header + -td --read-xfer-detect + ignore TS specified in the file meta header - -te --read-xfer-little - read with explicit VR little endian TS + -te --read-xfer-little + read with explicit VR little endian TS - -tb --read-xfer-big - read with explicit VR big endian TS + -tb --read-xfer-big + read with explicit VR big endian TS - -ti --read-xfer-implicit - read with implicit VR little endian TS + -ti --read-xfer-implicit + read with implicit VR little endian TS +.fi +.PP +.SS "processing options" +.PP +.nf +encoding of infinity and not-a-number: + -es --encode-strict + report error for 'inf' and 'nan' (default) + + -ee --encode-extended + permit 'inf' and 'nan' in JSON numbers .fi .PP .SS "output options" @@ -92,18 +103,18 @@ input transfer syntax: .nf output format: - +fc --formatted-code - enable whitespace formatting (default) + +fc --formatted-code + enable whitespace formatting (default) - # prints additional spaces and newlines for increased - # readability + # prints additional spaces and newlines for increased + # readability - -fc --compact-code - print only required characters + -fc --compact-code + print only required characters - +m --write-meta - write data set with meta information - (warning: not conforming to the DICOM standard) + +m --write-meta + write data set with meta information + (warning: not conforming to the DICOM standard) .fi .PP .SH "JSON Format" @@ -268,11 +279,11 @@ The basic structure of the JSON output created from a DICOM file looks like the .fi .PP .SS "Bulk Data" -Binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB or OW, as well as OD, OF and UN values are by default not written to the JSON output because of their size\&. Instead, for each element, a new Universally Unique Identifier (UUID) is being generated and written as an value of a BulkDataURI JSON element\&. So far, there is no possibility to write an additional file to hold the binary data for each of the binary data chunks\&. +Binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB or OW, as well as OD, OF, OL, OV and UN values are always written as 'InlineBinary' (base64 encoding) to the JSON output\&. A future version of this tool might optionally use a 'BulkDataURI' instead, i\&.e\&. the WADO-RS URL of a bulk data item that contains the element value\&. This would be particularly useful for large amounts of data, such as pixel data\&. .SH "NOTES" .PP .SS "Character Encoding" -\fBdcm2json\fP always tries to output in UTF-8 encoding\&. If this is not possible, e\&.g\&. because there is no support for character set conversion, ASCII is used instead (which is a subset of UTF-8)\&. +As required by the DICOM JSON encoding, \fBdcm2json\fP always creates output in Unicode UTF-8 encoding and converts DICOM datasets accordingly\&. If this is not possible, for example because DCMTK has been compiled without either iconv or ICU library, an error is returned\&. .SH "LOGGING" .PP The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&. @@ -285,6 +296,36 @@ All command line tools use the following notation for parameters: square bracket Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&. .PP In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI/dumppat\&.txt\fP)\&. +.SH "EXIT CODES" +.PP +The \fBdcm2json\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&. +.SS "general" +.PP +.nf +EXITCODE_NO_ERROR 0 +EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 +.fi +.PP +.SS "input file errors" +.PP +.nf +EXITCODE_CANNOT_READ_INPUT_FILE 20 +EXITCODE_NO_INPUT_FILES 21 +.fi +.PP +.SS "output file errors" +.PP +.nf +EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 +.fi +.PP +.SS "processing errors" +.PP +.nf +EXITCODE_CANNOT_CONVERT_TO_UNICODE 80 +EXITCODE_CANNOT_WRITE_VALID_JSON 81 +.fi +.PP .SH "ENVIRONMENT" .PP The \fBdcm2json\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&. @@ -292,4 +333,4 @@ The \fBdcm2json\fP utility will attempt to load DICOM data dictionaries specifie The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 2016-2017 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2016-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcm2pdf.1 b/doxygen/manpages/man1/dcm2pdf.1 index 91e2a669..567d7850 100644 --- a/doxygen/manpages/man1/dcm2pdf.1 +++ b/doxygen/manpages/man1/dcm2pdf.1 @@ -1,4 +1,4 @@ -.TH "dcm2pdf" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcm2pdf" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcm2pdf \- Extract PDF file from DICOM encapsulated PDF diff --git a/doxygen/manpages/man1/dcm2pnm.1 b/doxygen/manpages/man1/dcm2pnm.1 index d739b52b..6da25172 100644 --- a/doxygen/manpages/man1/dcm2pnm.1 +++ b/doxygen/manpages/man1/dcm2pnm.1 @@ -1,4 +1,4 @@ -.TH "dcm2pnm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcm2pnm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcm2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF or BMP @@ -124,7 +124,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -325,7 +325,7 @@ PNG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -452,4 +452,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmj2pnm\fP(1), \fBimg2dcm\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1998-2014 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1998-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcm2xml.1 b/doxygen/manpages/man1/dcm2xml.1 index 72f1554c..a4701929 100644 --- a/doxygen/manpages/man1/dcm2xml.1 +++ b/doxygen/manpages/man1/dcm2xml.1 @@ -1,4 +1,4 @@ -.TH "dcm2xml" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcm2xml" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcm2xml \- Convert DICOM file and data set to XML @@ -204,7 +204,7 @@ The basic structure of the DCMTK-specific XML output created from a DICOM file l - 256\\0\\8 + 256\0\8 ... @@ -230,11 +230,11 @@ Multiple values (i\&.e\&. where the DICOM value multiplicity is greater than 1) .PP The description of the Native DICOM Model format can be found in the DICOM standard, part 19 ('Application Hosting')\&. .SS "Bulk Data" -Binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB or OW, as well as OD, OF, OV and UN values are by default not written to the XML output because of their size\&. Instead, for each element, a new Universally Unique Identifier (UUID) is being generated and written as an attribute of a XML element\&. So far, there is no possibility to write an additional file to hold the binary data for each of the binary data chunks\&. This is not required by the standard, however, it might be useful for implementing an Application Hosting interface; thus this feature may be available in future versions of \fBdcm2xml\fP\&. +Binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB or OW, as well as OD, OF, OL, OV and UN values are by default not written to the XML output because of their size\&. Instead, for each element, a new Universally Unique Identifier (UUID) is being generated and written as an attribute of a XML element\&. So far, there is no possibility to write an additional file to hold the binary data for each of the binary data chunks\&. This is not required by the standard, however, it might be useful for implementing an Application Hosting interface; thus this feature may be available in future versions of \fBdcm2xml\fP\&. .PP -In addition, Supplement 163 (Store Over the Web by Representational State Transfer Services) introduces a new XML element that allows for encoding binary data as Base64\&. Currently, the command line option \fI--encode-base64\fP enables this encoding for the following VRs: OB, OD, OF, OV, OW and UN\&. +In addition, Supplement 163 (Store Over the Web by Representational State Transfer Services) introduces a new XML element that allows for encoding binary data as Base64\&. Currently, the command line option \fI--encode-base64\fP enables this encoding for the following VRs: OB, OD, OF, OL, OV, OW and UN\&. .SS "Known Issues" -In addition to what is written in the above section on 'Bulk Data', there are further known issues with the current implementation of the Native DICOM Model format\&. For example, large element values with a VR other than OB, OD, OF, OV, OW or UN are currently never written as bulk data, although it might be useful, e\&.g\&. for very long text elements (especially UT) or very long numeric fields (of various VRs)\&. +In addition to what is written in the above section on 'Bulk Data', there are further known issues with the current implementation of the Native DICOM Model format\&. For example, large element values with a VR other than OB, OD, OF, OL, OV, OW or UN are currently never written as bulk data, although it might be useful, e\&.g\&. for very long text elements (especially UT) or very long numeric fields (of various VRs)\&. .SH "NOTES" .PP .SS "Character Encoding" @@ -286,4 +286,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBxml2dcm\fP(1), \fBdcmconv\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2002-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2002-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmcjpeg.1 b/doxygen/manpages/man1/dcmcjpeg.1 index 67cdca11..8b229545 100644 --- a/doxygen/manpages/man1/dcmcjpeg.1 +++ b/doxygen/manpages/man1/dcmcjpeg.1 @@ -1,4 +1,4 @@ -.TH "dcmcjpeg" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmcjpeg" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmcjpeg \- Encode DICOM file to JPEG transfer syntax diff --git a/doxygen/manpages/man1/dcmcjpls.1 b/doxygen/manpages/man1/dcmcjpls.1 index f8ac8bc4..686582d6 100644 --- a/doxygen/manpages/man1/dcmcjpls.1 +++ b/doxygen/manpages/man1/dcmcjpls.1 @@ -1,4 +1,4 @@ -.TH "dcmcjpls" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmcjpls" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmcjpls \- Encode DICOM file to JPEG-LS transfer syntax @@ -160,13 +160,6 @@ JPEG-LS interleave: # In sample-interleave mode each pixel's components are encoded before # the next pixel is encoded. - +in --interleave-none - force uninterleaved JPEG-LS images - - # This flag forces uninterleaved mode for the resulting image. - # In this mode, each of the image's components are completely encoded - # before the next component is handled. - +iv --interleave-default use the fastest possible interleave mode @@ -345,4 +338,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmdjpls\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2009-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2009-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmconv.1 b/doxygen/manpages/man1/dcmconv.1 index cc6d6033..bad701c7 100644 --- a/doxygen/manpages/man1/dcmconv.1 +++ b/doxygen/manpages/man1/dcmconv.1 @@ -1,4 +1,4 @@ -.TH "dcmconv" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmconv" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmconv \- Convert DICOM file encoding @@ -243,11 +243,11 @@ other processing options: .nf output file format: - +F --write-file - write file format (default) - +Fm --write-new-meta-info - write file format with new meta information + write file format with new meta information (default) + + +F --write-file + write file format -F --write-dataset write data set without file meta information @@ -347,4 +347,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmdump\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1994-2017 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1994-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmcrle.1 b/doxygen/manpages/man1/dcmcrle.1 index d02e8c1c..ded40cfa 100644 --- a/doxygen/manpages/man1/dcmcrle.1 +++ b/doxygen/manpages/man1/dcmcrle.1 @@ -1,4 +1,4 @@ -.TH "dcmcrle" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmcrle" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmcrle \- Encode DICOM file to RLE transfer syntax diff --git a/doxygen/manpages/man1/dcmdjpeg.1 b/doxygen/manpages/man1/dcmdjpeg.1 index 7a2e7395..238485a1 100644 --- a/doxygen/manpages/man1/dcmdjpeg.1 +++ b/doxygen/manpages/man1/dcmdjpeg.1 @@ -1,4 +1,4 @@ -.TH "dcmdjpeg" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmdjpeg" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmdjpeg \- Decode JPEG-compressed DICOM file diff --git a/doxygen/manpages/man1/dcmdjpls.1 b/doxygen/manpages/man1/dcmdjpls.1 index 1ce5cc83..d2a75b3b 100644 --- a/doxygen/manpages/man1/dcmdjpls.1 +++ b/doxygen/manpages/man1/dcmdjpls.1 @@ -1,4 +1,4 @@ -.TH "dcmdjpls" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmdjpls" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmdjpls \- Decode JPEG-LS compressed DICOM file diff --git a/doxygen/manpages/man1/dcmdrle.1 b/doxygen/manpages/man1/dcmdrle.1 index 4e016c4b..8c7fe207 100644 --- a/doxygen/manpages/man1/dcmdrle.1 +++ b/doxygen/manpages/man1/dcmdrle.1 @@ -1,4 +1,4 @@ -.TH "dcmdrle" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmdrle" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmdrle \- Decode RLE-compressed DICOM file diff --git a/doxygen/manpages/man1/dcmdspfn.1 b/doxygen/manpages/man1/dcmdspfn.1 index 6c2fd3a0..37d6dd4f 100644 --- a/doxygen/manpages/man1/dcmdspfn.1 +++ b/doxygen/manpages/man1/dcmdspfn.1 @@ -1,4 +1,4 @@ -.TH "dcmdspfn" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmdspfn" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmdspfn \- Export standard display curves to a text file diff --git a/doxygen/manpages/man1/dcmdump.1 b/doxygen/manpages/man1/dcmdump.1 index 0071f849..fd00a35e 100644 --- a/doxygen/manpages/man1/dcmdump.1 +++ b/doxygen/manpages/man1/dcmdump.1 @@ -1,4 +1,4 @@ -.TH "dcmdump" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmdump" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmdump \- Dump DICOM file and data set diff --git a/doxygen/manpages/man1/dcmftest.1 b/doxygen/manpages/man1/dcmftest.1 index 32164045..8c35a96b 100644 --- a/doxygen/manpages/man1/dcmftest.1 +++ b/doxygen/manpages/man1/dcmftest.1 @@ -1,4 +1,4 @@ -.TH "dcmftest" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmftest" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmftest \- Test if file uses DICOM part 10 format diff --git a/doxygen/manpages/man1/dcmgpdir.1 b/doxygen/manpages/man1/dcmgpdir.1 index 51031df5..884079b7 100644 --- a/doxygen/manpages/man1/dcmgpdir.1 +++ b/doxygen/manpages/man1/dcmgpdir.1 @@ -1,4 +1,4 @@ -.TH "dcmgpdir" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmgpdir" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmgpdir \- Create a general purpose DICOMDIR diff --git a/doxygen/manpages/man1/dcmicmp.1 b/doxygen/manpages/man1/dcmicmp.1 index 25f668bf..9426d936 100644 --- a/doxygen/manpages/man1/dcmicmp.1 +++ b/doxygen/manpages/man1/dcmicmp.1 @@ -1,4 +1,4 @@ -.TH "dcmicmp" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmicmp" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmicmp \- Compare DICOM images and compute difference metrics diff --git a/doxygen/manpages/man1/dcmj2pnm.1 b/doxygen/manpages/man1/dcmj2pnm.1 index 942ee2ac..21785103 100644 --- a/doxygen/manpages/man1/dcmj2pnm.1 +++ b/doxygen/manpages/man1/dcmj2pnm.1 @@ -1,4 +1,4 @@ -.TH "dcmj2pnm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmj2pnm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmj2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF, JPEG or BMP @@ -124,7 +124,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -394,7 +394,7 @@ JPEG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -530,4 +530,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcm2pnm\fP(1), \fBimg2dcm\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2001-2018 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2001-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcml2pnm.1 b/doxygen/manpages/man1/dcml2pnm.1 index 4805c785..6b30e479 100644 --- a/doxygen/manpages/man1/dcml2pnm.1 +++ b/doxygen/manpages/man1/dcml2pnm.1 @@ -1,4 +1,4 @@ -.TH "dcml2pnm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcml2pnm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcml2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF or BMP @@ -124,7 +124,7 @@ flipping: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -325,7 +325,7 @@ PNG format: other transformations: +G --grayscale - convert to grayscale if necessary + convert color image to grayscale (monochrome) +P --change-polarity change polarity (invert pixel output) @@ -454,4 +454,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcm2pnm\fP(1), \fBimg2dcm\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2001-2014 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2001-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmmkcrv.1 b/doxygen/manpages/man1/dcmmkcrv.1 index a66766a7..7c840a1c 100644 --- a/doxygen/manpages/man1/dcmmkcrv.1 +++ b/doxygen/manpages/man1/dcmmkcrv.1 @@ -1,4 +1,4 @@ -.TH "dcmmkcrv" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmmkcrv" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmmkcrv \- Add 2D curve data to image diff --git a/doxygen/manpages/man1/dcmmkdir.1 b/doxygen/manpages/man1/dcmmkdir.1 index cc7c784a..982ef18b 100644 --- a/doxygen/manpages/man1/dcmmkdir.1 +++ b/doxygen/manpages/man1/dcmmkdir.1 @@ -1,4 +1,4 @@ -.TH "dcmmkdir" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmmkdir" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmmkdir \- Create a DICOMDIR file diff --git a/doxygen/manpages/man1/dcmmklut.1 b/doxygen/manpages/man1/dcmmklut.1 index 8870b8c7..64a06270 100644 --- a/doxygen/manpages/man1/dcmmklut.1 +++ b/doxygen/manpages/man1/dcmmklut.1 @@ -1,4 +1,4 @@ -.TH "dcmmklut" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmmklut" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmmklut \- Create DICOM look-up tables diff --git a/doxygen/manpages/man1/dcmodify.1 b/doxygen/manpages/man1/dcmodify.1 index a87f9b0e..164f6394 100644 --- a/doxygen/manpages/man1/dcmodify.1 +++ b/doxygen/manpages/man1/dcmodify.1 @@ -1,4 +1,4 @@ -.TH "dcmodify" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmodify" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmodify \- Modify DICOM files @@ -30,6 +30,8 @@ where 'sequence' is a sequence tag like (0008,1111) or a dictionary name for a t .PP When inserting tag paths consisting of multiple nodes (i\&.e\&. not a single element) using the \fI-i\fP option, any missing path elements (items, sequences, leaf elements) are inserted automatically when missing\&. That does not work for item wildcards: When no single item exists in the surrounding sequence \fBdcmodify\fP of course can't decide, how many items should be generated\&. However, if specifying an item number like '5', all 6 items (counted from zero) can be (and are) automatically generated in insert mode\&. If already 2 items would exist, the rest (4) would be inserted\&. .PP +\fBdcmodify\fP does not work on directories, i\&.e\&. the parameter \fIdcmfile-in\fP\&.\&.\&. must not include directory names\&. +.PP Please note that there are some issues concerning the modification of private tags (see PRIVATE TAGS section) and for changing UIDs (CHANGING UIDs section)\&. .SH "PARAMETERS" .PP @@ -292,6 +294,8 @@ For the deletion of private non-reservation tags there are no special issues\&. If you generate new UID's with \fI-gst\fP, \fI-gse\fP or \fI-gin\fP, this will only affect the UID you chose to generate\&. So if you use \fI-gst\fP to generate a new 'Study Instance UID', then 'Series Instance UID' and 'SOP Instance UID' will not be affected! This gives you the possibility to generate each value separately\&. Normally, you would also modify the 'underlying' UIDs\&. As a disadvantage of this flexibility, the user has to assure, that when creating 'new' DICOM files with new UIDs with \fBdcmodify\fP, other UIDs have to be updated by the user as necessary\&. .PP When choosing the \fI-gin\fP option, the related metaheader tag ('Media Storage SOP Instance UID') is updated automatically\&. This behavior cannot be disabled\&. +.PP +When working on multiple input files, \fBdcmodify\fP processes each file in isolated fashion, i\&.e\&. it will generate UIDs for each single file\&. For example, when using the \fI-gst\fP option, \fBdcmodify\fP will insert a different Study Instance UID into each file instead of generating a single one and writing it to each file that is being processed\&. .SH "CREATING NEW FILES" .PP Option \fI--create-file\fP lets \fBdcmodify\fP create a file if it does not already exist on disk\&. This can be used in order to create files from scratch by performing consecutive insertions with options like \fI--insert\fP\&. This might especially become handy when creating query files for tools like \fBfindscu\fP or \fBmovescu\fP\&. In case no specific output transfer syntax is defined, \fBdcmodify\fP chooses Little Endian Explicit Uncompressed for output\&. Files that are newly created are always written as DICOM file format, i\&.e\&. option \fI--write-dataset\fP is not permitted together with \fI--create\fP\&. This way, at least the metaheader is written and no file with zero byte length is created in a case where no insertions are performed in the \fBdcmodify\fP call\&. diff --git a/doxygen/manpages/man1/dcmp2pgm.1 b/doxygen/manpages/man1/dcmp2pgm.1 index 3b16c7bd..15673c80 100644 --- a/doxygen/manpages/man1/dcmp2pgm.1 +++ b/doxygen/manpages/man1/dcmp2pgm.1 @@ -1,4 +1,4 @@ -.TH "dcmp2pgm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmp2pgm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmp2pgm \- Read DICOM image and presentation state and render bitmap diff --git a/doxygen/manpages/man1/dcmprscp.1 b/doxygen/manpages/man1/dcmprscp.1 index 3d94739f..2bb8be7b 100644 --- a/doxygen/manpages/man1/dcmprscp.1 +++ b/doxygen/manpages/man1/dcmprscp.1 @@ -1,4 +1,4 @@ -.TH "dcmprscp" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmprscp" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmprscp \- DICOM basic grayscale print management SCP diff --git a/doxygen/manpages/man1/dcmprscu.1 b/doxygen/manpages/man1/dcmprscu.1 index 3fa91104..a1394c10 100644 --- a/doxygen/manpages/man1/dcmprscu.1 +++ b/doxygen/manpages/man1/dcmprscu.1 @@ -1,4 +1,4 @@ -.TH "dcmprscu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmprscu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmprscu \- Print spooler for presentation state viewer diff --git a/doxygen/manpages/man1/dcmpschk.1 b/doxygen/manpages/man1/dcmpschk.1 index 61d4ec77..50fe37c2 100644 --- a/doxygen/manpages/man1/dcmpschk.1 +++ b/doxygen/manpages/man1/dcmpschk.1 @@ -1,4 +1,4 @@ -.TH "dcmpschk" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmpschk" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmpschk \- Checking tool for presentation states diff --git a/doxygen/manpages/man1/dcmpsmk.1 b/doxygen/manpages/man1/dcmpsmk.1 index e5742b74..ee7b233f 100644 --- a/doxygen/manpages/man1/dcmpsmk.1 +++ b/doxygen/manpages/man1/dcmpsmk.1 @@ -1,4 +1,4 @@ -.TH "dcmpsmk" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmpsmk" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmpsmk \- Create DICOM grayscale softcopy presentation state diff --git a/doxygen/manpages/man1/dcmpsprt.1 b/doxygen/manpages/man1/dcmpsprt.1 index 187cfb09..7e4f05ff 100644 --- a/doxygen/manpages/man1/dcmpsprt.1 +++ b/doxygen/manpages/man1/dcmpsprt.1 @@ -1,4 +1,4 @@ -.TH "dcmpsprt" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmpsprt" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmpsprt \- Read DICOM images and presentation states and render print job diff --git a/doxygen/manpages/man1/dcmpsrcv.1 b/doxygen/manpages/man1/dcmpsrcv.1 index f0f46548..13941623 100644 --- a/doxygen/manpages/man1/dcmpsrcv.1 +++ b/doxygen/manpages/man1/dcmpsrcv.1 @@ -1,4 +1,4 @@ -.TH "dcmpsrcv" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmpsrcv" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmpsrcv \- Network receive for presentation state viewer diff --git a/doxygen/manpages/man1/dcmpssnd.1 b/doxygen/manpages/man1/dcmpssnd.1 index 5a140240..ee067c0f 100644 --- a/doxygen/manpages/man1/dcmpssnd.1 +++ b/doxygen/manpages/man1/dcmpssnd.1 @@ -1,4 +1,4 @@ -.TH "dcmpssnd" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmpssnd" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmpssnd \- Network send for presentation state viewer diff --git a/doxygen/manpages/man1/dcmqridx.1 b/doxygen/manpages/man1/dcmqridx.1 index 5fb96897..b6112c5c 100644 --- a/doxygen/manpages/man1/dcmqridx.1 +++ b/doxygen/manpages/man1/dcmqridx.1 @@ -1,4 +1,4 @@ -.TH "dcmqridx" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmqridx" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmqridx \- Register a DICOM image file in an image database index file diff --git a/doxygen/manpages/man1/dcmqrscp.1 b/doxygen/manpages/man1/dcmqrscp.1 index ef668f0b..47f9ba71 100644 --- a/doxygen/manpages/man1/dcmqrscp.1 +++ b/doxygen/manpages/man1/dcmqrscp.1 @@ -1,4 +1,4 @@ -.TH "dcmqrscp" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmqrscp" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmqrscp \- DICOM image archive (central test node) @@ -731,6 +731,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -785,6 +791,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -824,6 +831,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -843,6 +852,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -996,4 +1012,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmqridx\fP(1), \fBdcmqrti\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1993-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1993-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmqrti.1 b/doxygen/manpages/man1/dcmqrti.1 index 146b723b..057b77fb 100644 --- a/doxygen/manpages/man1/dcmqrti.1 +++ b/doxygen/manpages/man1/dcmqrti.1 @@ -1,4 +1,4 @@ -.TH "dcmqrti" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmqrti" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmqrti \- The Terminal Initiator Telnet Client Program diff --git a/doxygen/manpages/man1/dcmquant.1 b/doxygen/manpages/man1/dcmquant.1 index 98e69f9a..6fb32214 100644 --- a/doxygen/manpages/man1/dcmquant.1 +++ b/doxygen/manpages/man1/dcmquant.1 @@ -1,4 +1,4 @@ -.TH "dcmquant" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmquant" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmquant \- Convert DICOM color images to palette color diff --git a/doxygen/manpages/man1/dcmrecv.1 b/doxygen/manpages/man1/dcmrecv.1 index d004899f..3702e0d8 100644 --- a/doxygen/manpages/man1/dcmrecv.1 +++ b/doxygen/manpages/man1/dcmrecv.1 @@ -1,4 +1,4 @@ -.TH "dcmrecv" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmrecv" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmrecv \- Simple DICOM storage SCP (receiver) @@ -84,6 +84,99 @@ other network options: -dhl --disable-host-lookup disable hostname lookup .fi .PP +.SS "transport layer security (TLS) options" +.PP +.nf +transport protocol stack: + + -tls --disable-tls + use normal TCP/IP connection (default) + + +tls --enable-tls [p]rivate key file, [c]ertificate file: string + use authenticated secure TLS connection + +private key password (only with --enable-tls): + + +ps --std-passwd + prompt user to type password on stdin (default) + + +pw --use-passwd [p]assword: string + use specified password + + -pw --null-passwd + use empty string as password + +key and certificate file format: + + -pem --pem-keys + read keys and certificates as PEM file (default) + + -der --der-keys + read keys and certificates as DER file + +certification authority: + + +cf --add-cert-file [f]ilename: string + add certificate file to list of certificates + + +cd --add-cert-dir [d]irectory: string + add certificates in d to list of certificates + +security profile: + + +px --profile-bcp195 + BCP 195 TLS Profile (default) + + +py --profile-bcp195-nd + Non-downgrading BCP 195 TLS Profile + + +pz --profile-bcp195-ex + Extended BCP 195 TLS Profile + + +pb --profile-basic + Basic TLS Secure Transport Connection Profile (retired) + + +pa --profile-aes + AES TLS Secure Transport Connection Profile (retired) + + +pn --profile-null + Authenticated unencrypted communication + (retired, was used in IHE ATNA) + +ciphersuite: + + +cc --list-ciphers + show list of supported TLS ciphersuites and exit + + +cs --cipher [c]iphersuite name: string + add ciphersuite to list of negotiated suites + + +dp --dhparam [f]ilename: string + read DH parameters for DH/DSS ciphersuites + +pseudo random generator: + + +rs --seed [f]ilename: string + seed random generator with contents of f + + +ws --write-seed + write back modified seed (only with --seed) + + +wf --write-seed-file [f]ilename: string (only with --seed) + write modified seed to file f + +peer authentication: + + -rc --require-peer-cert + verify peer certificate, fail if absent (default) + + -vc --verify-peer-cert + verify peer certificate if present + + -ic --ignore-peer-cert + don't verify peer certificate +.fi +.PP .SS "output options" .PP .nf @@ -264,6 +357,7 @@ EXITCODE_INVALID_OUTPUT_DIRECTORY 45 EXITCODE_CANNOT_INITIALIZE_NETWORK 60 (*) EXITCODE_CANNOT_START_SCP_AND_LISTEN 64 EXITCODE_INVALID_ASSOCIATION_CONFIG 66 +EXITCODE_CANNOT_CREATE_TRANSPORT_LAYER 71 .fi .PP .PP @@ -283,4 +377,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmsend\fP(1), \fBstorescu\fP(1), \fBstorescp\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2013-2017 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2013-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmscale.1 b/doxygen/manpages/man1/dcmscale.1 index be9b53bd..1ce395f1 100644 --- a/doxygen/manpages/man1/dcmscale.1 +++ b/doxygen/manpages/man1/dcmscale.1 @@ -1,4 +1,4 @@ -.TH "dcmscale" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmscale" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmscale \- Scale DICOM images @@ -91,7 +91,7 @@ input transfer syntax: scaling: +a --recognize-aspect - recognize pixel aspect ratio (default) + recognize pixel aspect ratio when scaling (default) -a --ignore-aspect ignore pixel aspect ratio when scaling @@ -230,4 +230,4 @@ The \fBdcmscale\fP utility will attempt to load DICOM data dictionaries specifie The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 2002-2014 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2002-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcmsend.1 b/doxygen/manpages/man1/dcmsend.1 index 586d8e43..496049b7 100644 --- a/doxygen/manpages/man1/dcmsend.1 +++ b/doxygen/manpages/man1/dcmsend.1 @@ -1,4 +1,4 @@ -.TH "dcmsend" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmsend" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmsend \- Simple DICOM storage SCU (sender) diff --git a/doxygen/manpages/man1/dcmsign.1 b/doxygen/manpages/man1/dcmsign.1 index f218466a..0e2e4cdf 100644 --- a/doxygen/manpages/man1/dcmsign.1 +++ b/doxygen/manpages/man1/dcmsign.1 @@ -1,4 +1,4 @@ -.TH "dcmsign" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcmsign" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcmsign \- Sign and Verify DICOM Files @@ -98,6 +98,14 @@ input transfer syntax: -ti --read-xfer-implicit read with implicit VR little endian TS + +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known .fi .PP .SS "signature commands" @@ -112,6 +120,10 @@ input transfer syntax: +si --sign-item [k]eyfile, [c]ertfile, [i]tem location: string create signature in sequence item + +t --insert-timestamp ts[q]file, ts[r]file [u]idfile: string + insert certified timestamp from ts response r + from timestamp query q at signature UID u + +r --remove [s]ignature UID: string remove signature @@ -119,7 +131,83 @@ input transfer syntax: remove all signatures from data set .fi .PP -.SS "signature creation options (only with –sign or –sign-item):" +.SS "general signature options" +.PP +.nf +key and certificate file format: + + -pem --pem-keys + read keys/certificates as PEM file (default) + + -der --der-keys + read keys/certificates as DER file + +signature format: + + -fn --format-new + use correct DICOM signature format (default) + + -fo --format-old + use old (pre-3.5.4) DCMTK signature format, non-conformant + if signature includes compressed pixel data. This option should + only be used to verify signatures in the old format. +.fi +.PP +.SS "signature verification options (only with –verify)" +.PP +.nf +signature verification: + + +rv --verify-if-present + verify signatures if present, pass otherwise + (default) + + +rg --require-sig + fail if no signature at all is present + + +rc --require-creator + fail if no creator RSA signature is present + + +ru --require-auth + fail if no auth RSA signature is present + + +rs --require-sr + fail if no SR RSA signature is present + +timestamp verification: + + +tv --verify-ts + verify certified timestamp if present (default) + + -tv --ignore-ts + ignore certified timestamps + + +tr --require-ts + fail if no certified timestamp is present + +certification authority: + + +cf --add-cert-file + [f]ilename: string + add trusted certificate file to cert store + + +uf --add-ucert-file + [f]ilename: string + add untrusted intermediate certificate file + + +cd --add-cert-dir + [d]irectory: string + add certificates in d to cert store + + +cr --add-crl-file + [f]ilename: string + add certificate revocation list file + (implies --enable-crl-vfy) + + +cl --enable-crl-vfy + enable certificate revocation list verification.fi +.PP +.SS "signature creation options (only with –sign or –sign-item)" .PP .nf private key password: @@ -133,14 +221,6 @@ private key password: -pw --null-passwd use empty string as password -key and certificate file format: - - -pem --pem-keys - read keys/certificates as PEM file (default) - - -der --der-keys - read keys/certificates as DER file - digital signature profile: -pf --profile-none @@ -155,6 +235,12 @@ digital signature profile: +pa --profile-auth enforce authorization signature profile + +pr --profile-sr + enforce SR RSA signature profile + + +pv --profile-srv + enforce SR RSA signature profile (verification) + MAC algorithm: +mr --mac-ripemd160 @@ -166,6 +252,27 @@ MAC algorithm: +mm --mac-md5 use MD 5 + +m2 --mac-sha256 + use SHA-256 + + +m3 --mac-sha384 + use SHA-384 + + +m5 --mac-sha512 + use SHA-512 + +signature purpose: + + +lp --list-purposes + show list of signature purpose codes and exit + + -sp --no-sig-purpose + do not add signature purpose (default) + + +sp --sig-purpose + [p]urpose code: integer (1..18) + add digital signature purpose code p + tag selection: -t --tag @@ -174,16 +281,62 @@ tag selection: (this option can be specified multiple times) -tf --tag-file [f]ilename: string - read list of tags from text file + read list of tags from text file.fi +.PP +.SS "timestamp creation options (only with –sign or –sign-item)" +.PP +.nf +timestamp creation: -signature format: + -ts --timestamp-off + do not create timestamp (default) - -fn --format-new - use correct DICOM signature format (default) + +ts --timestamp-file [t]sq-filename, [u]id-filename: string + create timestamp query file t and uid file u - -fo --format-old - use old (pre-3.5.4) DCMTK signature format, non-conformant - if signature includes compressed pixel data +timestamp MAC algorithm (only with --timestamp-file): + + +tm2 --ts-mac-sha256 + use SHA-256 (default) + + +tm3 --ts-mac-sha384 + use SHA-384 + + +tm5 --ts-mac-sha512 + use SHA-512 + + +tmr --ts-mac-ripemd160 + use RIPEMD 160 + + +tms --ts-mac-sha1 + use SHA-1 (not recommended) + + +tmm --ts-mac-md5 + use MD5 (not recommended) + +timestamp query nonce options (only with --timestamp-file): + + +tn --ts-use-nonce + include random nonce (default) + + -tn --ts-no-nonce + do not include nonce + +timestamp certificate inclusion options (only with --timestamp-file): + + +tc --ts-request-cert + request TSA certificate in timestamp (default) + + -tc --ts-no-cert + do not request TSA certificate in timestamp + +timestamp policy options (only with --timestamp-file): + + -tp --ts-no-policy + do not specify ts policy (default) + + +tp --ts-policy [p]olicy-OID: string + request timestamp policy p .fi .PP .SS "output options" @@ -223,13 +376,13 @@ other output options: .SS "Files and Parameters" The \fBdcmsign\fP utility reads and writes a number of files and file formats which are described in this section\&. .PP -Public Key Certificates are expected in X\&.509v3 format, either with PEM or DER encoding\&. The dcmsign utility currently supports RSA and DSA public keys, although only RSA keys are defines in the Security Profiles of the DICOM standard\&. +Public Key Certificates are expected in X\&.509v3 format, either with PEM or DER encoding\&. The \fBdcmsign\fP utility currently supports RSA and DSA public keys, although only RSA keys are defines in the Security Profiles of the DICOM standard\&. .PP Private Keys are expected in PEM or DER encoding\&. PEM is recommended (and default) because this allows one to keep private keys in encrypted form\&. Command line options control the behavior of \fBdcmsign\fP when an encrypted PEM key is opened (see above)\&. In general it is not recommended to specify the encryption password in the command line because the command line may be visible to other processes in the system, e\&.g\&. 'ps -ef'\&. .PP -The list of data elements to sign can either be read from a file or specified on the command line or both (in this case the keys are combined)\&. +By default, \fBdcmsign\fP will create a signature covering all data elements in the dataset or item\&. This default can be overridden by explicitly specifying a list of data elements (attribute tags)\&. This list can either be read from a file or specified on the command line or both (in this case the attribute tags are combined)\&. .PP -On the command line, attribute keys are specified as +On the command line, attribute tags are specified as .PP .PP .nf @@ -240,7 +393,9 @@ On the command line, attribute keys are specified as .fi .PP .PP -When attribute tags are read from file with the \fI--tag-file\fP option, a plain text file of max\&. 64 kbyte is expected\&. Tags within the file are either symbolic names from the data dictionary or have the format (gggg,eeee) (with braces)\&. Tags are separated by one or more whitespace characters\&. +When attribute tags are read from file with the \fI--tag-file\fP option, a plain text file is expected\&. Tags within the file are either symbolic names from the data dictionary or have the format (gggg,eeee) (with braces)\&. Tags are separated by one or more whitespace characters\&. +.PP +The currently selected digital signature profile may specify additional attribute tags required to be included in the signature, which will be silently added\&. .PP The \fI--sign-item\fP operation requires a location string that describes in which sequence item a signature is to be created\&. The location string has the following format: .PP @@ -259,6 +414,20 @@ ReferencedSeriesSequence[0].ReferencedImageSequence[1] .PP .PP would cause a digital signature to be created in the second item of the ReferencedImageSequence (0008,1140) which is located in the first item of the ReferencedSeriesSequence (0008,1115) which is located in the main DICOM dataset\&. +.SS "Certified Timestamps" +Starting with release 3\&.6\&.6, \fBdcmsign\fP offers support for certified timestamps according to RFC 3161\&. For now, the tool does not implement any of the network protocols defined in RFC 3161 for communicating with a timestamp authority (TSA), but it can write a timestamp query (TSQ) during signature creation, and the new command \fI--insert-timestamp\fP will read a timestamp response (TSR) from file and add it to the DICOM digital signature\&. Since a DICOM file can contain multiple signatures, a 'UID file' (which contains the Digital Signature UID) is used to identify the signature to which the TSR should be added\&. The \fBdcmsign\fP tool will also perform various consistency checks before storing the timestamp\&. +.PP +During signature verification, the presence of a certified timestamp will be detected and the timestamp will also be verified unless option \fI--ignore-ts\fP was used\&. Signature verification and timestamp verification use a common certificate store to check the certificates of the DICOM signature and the timestamp\&. This store can be populated with the options \fI--add-cert-file\fP and \fI--add-cert-dir\fP, which both add trusted CA certificates, \fI--add-ucert-file\fP, which adds an untrusted intermediate CA certificate, and \fI--add-crl-file\fP, which adds a certificate revocation list\&. +.SS "Hashed Certificate Directories" +Instead of adding CA certificates and certificate revocation lists (CRLs) manually using \fI--add-cert-file\fP and \fI--add-crl-file\fP, the user can set-up a directory where \fBdcmsign\fP will look-up and load certificates and CRLs from as needed, using \fI--add-cert-dir\fP\&. +.PP +Th directory should contain one certificate or CRL per file in PEM format, with a filename of the form hash\&.N for a certificate, or hash\&.rN for a CRL\&. The hash is the value returned by +.PP +\fIopenssl x509 -hash -noout -in \fP (for a certificate) \fIopenssl crl -hash -noout -in \fP (for a CRL) +.PP +The \&.N or \&.rN suffix is a sequence number that starts at zero, and is incremented consecutively for each certificate or CRL with the same hash value\&. Gaps in the sequence numbers are not supported, it is assumed that there are no more objects with the same hash beyond the first missing number in the sequence\&. +.PP +CRLs will only be verified when option \fI--enable-crl-vfy\fP is specified\&. In this case, \fBdcmsign\fP will expect a CRL to be present for each CA and will fail signature verification if no CRL can be found for the CA that issued the signer certificate\&. .SH "LOGGING" .PP The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&. @@ -271,6 +440,56 @@ All command line tools use the following notation for parameters: square bracket Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&. .PP In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI/dumppat\&.txt\fP)\&. +.SH "EXIT CODES" +.PP +The \fBdcmsign\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&. +.SS "general" +.PP +.nf +EXITCODE_NO_ERROR 0 +EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 +EXITCODE_NOOPENSSL 5 +.fi +.PP +.SS "input file errors" +.PP +.nf +EXITCODE_CANNOT_READ_INPUT_FILE 20 +EXITCODE_NO_INPUT_FILES 21 +EXITCODE_CANNOT_READ_TAG_FILE 30 +EXITCODE_CANNOT_READ_TSQ_FILE 31 +EXITCODE_CANNOT_READ_TSR_FILE 32 +EXITCODE_CANNOT_READ_UID_FILE 33 +.fi +.PP +.SS "output file errors" +.PP +.nf +EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 +EXITCODE_CANNOT_WRITE_SUPPORT_FILE 46 +.fi +.PP +.SS "processing errors" +.PP +.nf +EXITCODE_CANNOT_ACCESS_SIGNATURE 80 +EXITCODE_CANNOT_ACCESS_TS 81 +EXITCODE_CANNOT_INSERT_TS 82 +EXITCODE_SIGNATURE_REMOVAL_FAILED 83 +EXITCODE_SIGNATURE_UID_NOT_FOUND 84 +EXITCODE_SIGNATURE_CREATION_FAILED 85 +EXITCODE_SYNTAX_ERROR_IN_TAG_FILE 86 +EXITCODE_TS_CONSISTENCY_CHECK_FAILED 87 +.fi +.PP +.SS "application specific errors" +.PP +.nf +EXITCODE_NO_SIGNATURES_PRESENT 100 +EXITCODE_SIGNATURE_VERIFICATION_FAILED 101 +EXITCODE_SIGNATURE_VERIFICATION_POLICY 102 +.fi +.PP .SH "ENVIRONMENT" .PP The \fBdcmsign\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&. @@ -278,4 +497,4 @@ The \fBdcmsign\fP utility will attempt to load DICOM data dictionaries specified The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 2000-2014 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2000-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/dcod2lum.1 b/doxygen/manpages/man1/dcod2lum.1 index ad1777a6..90adaa2e 100644 --- a/doxygen/manpages/man1/dcod2lum.1 +++ b/doxygen/manpages/man1/dcod2lum.1 @@ -1,4 +1,4 @@ -.TH "dcod2lum" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dcod2lum" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dcod2lum \- Convert hardcopy characteristic curve file to softcopy format diff --git a/doxygen/manpages/man1/dconvlum.1 b/doxygen/manpages/man1/dconvlum.1 index 7c5e3f22..2f5f8752 100644 --- a/doxygen/manpages/man1/dconvlum.1 +++ b/doxygen/manpages/man1/dconvlum.1 @@ -1,4 +1,4 @@ -.TH "dconvlum" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dconvlum" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dconvlum \- Convert VeriLUM files to DCMTK display files diff --git a/doxygen/manpages/man1/drtdump.1 b/doxygen/manpages/man1/drtdump.1 index dba43015..952fc703 100644 --- a/doxygen/manpages/man1/drtdump.1 +++ b/doxygen/manpages/man1/drtdump.1 @@ -1,4 +1,4 @@ -.TH "drtdump" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "drtdump" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME drtdump \- Dump DICOM RT file and data set diff --git a/doxygen/manpages/man1/dsr2html.1 b/doxygen/manpages/man1/dsr2html.1 index 25629347..7735cd91 100644 --- a/doxygen/manpages/man1/dsr2html.1 +++ b/doxygen/manpages/man1/dsr2html.1 @@ -1,4 +1,4 @@ -.TH "dsr2html" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dsr2html" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dsr2html \- Render DICOM SR file and data set to HTML/XHTML diff --git a/doxygen/manpages/man1/dsr2xml.1 b/doxygen/manpages/man1/dsr2xml.1 index 78e23142..7ca5f25b 100644 --- a/doxygen/manpages/man1/dsr2xml.1 +++ b/doxygen/manpages/man1/dsr2xml.1 @@ -1,4 +1,4 @@ -.TH "dsr2xml" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dsr2xml" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dsr2xml \- Convert DICOM SR file and data set to XML diff --git a/doxygen/manpages/man1/dsrdump.1 b/doxygen/manpages/man1/dsrdump.1 index af537c33..7b8817d6 100644 --- a/doxygen/manpages/man1/dsrdump.1 +++ b/doxygen/manpages/man1/dsrdump.1 @@ -1,4 +1,4 @@ -.TH "dsrdump" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dsrdump" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dsrdump \- Dump DICOM SR file and data set diff --git a/doxygen/manpages/man1/dump2dcm.1 b/doxygen/manpages/man1/dump2dcm.1 index a36c4ad3..a2903e18 100644 --- a/doxygen/manpages/man1/dump2dcm.1 +++ b/doxygen/manpages/man1/dump2dcm.1 @@ -1,4 +1,4 @@ -.TH "dump2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "dump2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME dump2dcm \- Convert ASCII dump to DICOM file @@ -195,13 +195,13 @@ VR: Value Representation must be written as 2 characters as in between the two characters. If the VR can be determined from the tag, this part of a line is optional. Value: There are several rules for writing values: - 1. US, SS, SL, UL, FD, FL, OD, OF and OL are written as decimal - strings that can be read by scanf(). + 1. US, SS, UL, SL, UV, SV, FD, FL, OD, OF, OL and OV are written + as decimal strings that can be read by scanf(). 2. AT is written as '(gggg,eeee)' with additional spaces stripped off automatically and gggg and eeee being decimal strings that can be read by scanf(). 3. OB and OW values are written as byte or word hexadecimal - values separated by '\\' character. Alternatively, OB or OW + values separated by '\' character. Alternatively, OB or OW values can be read from a separate file by writing the filename prefixed by a '=' character (e.g. '=largepix.dat'). The contents of the file will be read as is. By default, OW @@ -221,22 +221,24 @@ Value: There are several rules for writing values: line. Anything after the ']' is interpreted as comment. 7. '(' and '<' are interpreted special and may not be used when writing an input file by hand as beginning characters of a - string. Multiple Value are separated by '\\'. The lines + string. Multiple Value are separated by '\'. The lines need not be sorted into ascending tag order. References in DICOM Directories are not supported. Semantic errors are not detected. .fi .PP -.SS "Example" +.SS "Examples" +The following lines show valid examples of the syntax described above: +.PP .PP .nf (0008,0020) DA [19921012] # 8, 1 StudyDate (0008,0016) UI =MRImageStorage # 26, 1 SOPClassUID (0002,0012) UI [1.2.276.0.7230010.100.1.1] - (0020,0032) DS [0.0\\0.0] # 8, 2 ImagePositionPatient + (0020,0032) DS [0.0\0.0] # 8, 2 ImagePositionPatient (0028,0009) AT (3004,000c) # 4, 1 FrameIncrementPointer (0028,0010) US 256 # 4, 1 Rows - (0002,0001) OB 01\\00 + (0002,0001) OB 01\00 .fi .PP .SS "Limitations" @@ -263,4 +265,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcmdump\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1996-2016 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1996-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/echoscu.1 b/doxygen/manpages/man1/echoscu.1 index e7445acd..2125ad97 100644 --- a/doxygen/manpages/man1/echoscu.1 +++ b/doxygen/manpages/man1/echoscu.1 @@ -1,4 +1,4 @@ -.TH "echoscu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "echoscu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME echoscu \- DICOM verification (C-ECHO) SCU @@ -131,10 +131,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -254,4 +254,4 @@ The \fBechoscu\fP utility will attempt to load DICOM data dictionaries specified The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 1994-2018 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1994-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/findscu.1 b/doxygen/manpages/man1/findscu.1 index 6a33dd57..293165df 100644 --- a/doxygen/manpages/man1/findscu.1 +++ b/doxygen/manpages/man1/findscu.1 @@ -1,4 +1,4 @@ -.TH "findscu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "findscu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME findscu \- DICOM query (C-FIND) SCU @@ -124,6 +124,9 @@ other network options: -to --timeout [s]econds: integer (default: unlimited) timeout for connection requests + -ts --socket-timeout [s]econds: integer (default: 60) + timeout for network socket (0 for none) + -ta --acse-timeout [s]econds: integer (default: 30) timeout for ACSE messages @@ -178,10 +181,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -265,6 +268,10 @@ C-FIND responses: -Xs --extract-xml-single [f]ilename: string extract all responses to given XML file f + + -Xlo --limit-output [n]umber: integer + limit number of responses extracted to file to n + (default: unlimited) .fi .PP .SH "NOTES" @@ -371,4 +378,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBmovescu\fP(1), \fBdump2dcm\fP(1), \fBdcmodify\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1994-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1994-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/getscu.1 b/doxygen/manpages/man1/getscu.1 index b26f825d..cad0d80c 100644 --- a/doxygen/manpages/man1/getscu.1 +++ b/doxygen/manpages/man1/getscu.1 @@ -1,4 +1,4 @@ -.TH "getscu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "getscu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME getscu \- DICOM retrieve (C-GET) SCU diff --git a/doxygen/manpages/man1/img2dcm.1 b/doxygen/manpages/man1/img2dcm.1 index 08908565..8ffc2e0b 100644 --- a/doxygen/manpages/man1/img2dcm.1 +++ b/doxygen/manpages/man1/img2dcm.1 @@ -1,4 +1,4 @@ -.TH "img2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "img2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME img2dcm \- Convert standard image formats into DICOM format @@ -225,7 +225,7 @@ With the \fI--insert-type2\fP and \fI--invent-type1\fP options (both enabled per .PP .PD 0 .IP "\(bu" 2 -The \fI--key\fP option can be used to add further attributes to the DICOM output file\&. This option is applied at the very end, just before saving the DICOM file\&. It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&. +The \fI--key\fP option can be used to add further attributes to the DICOM output file\&. It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&. The \fI--key\fP option can be present more than once\&. The value part (after the '=') may be absent causing the attribute to be set with zero length\&. Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&. .PP .SS "UIDs" New Study and Series Instance UIDs are generated \fBif necessary\fP after applying the \fI--study-from\fP and \fI--series\fP options\&. If Study Instance UID or Series Instance UID are not present after these steps, they are newly generated, independently from each other\&. A contrary behavior is chosen for the SOP Instance UID that one could expect to be taken over when using the \fI--dataset-from\fP option\&. This is \fBnot\fP the case, the SOP Instance UID is \fBnot\fP copied to the new object\&. This should be the desirable behavior for most use cases\&. However, if a certain SOP Instance UID should be inserted into the new object, the \fI--key\fP option should be used\&. @@ -346,4 +346,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcm2pnm\fP(1), \fBdcmj2pnm\fP(1), \fBdump2dcm\fP(1), \fBdcmconv\fP(1), \fBdcmodify\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2007-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2007-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/movescu.1 b/doxygen/manpages/man1/movescu.1 index 35ce957b..752ef9b8 100644 --- a/doxygen/manpages/man1/movescu.1 +++ b/doxygen/manpages/man1/movescu.1 @@ -1,4 +1,4 @@ -.TH "movescu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "movescu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME movescu \- DICOM retrieve (C-MOVE) SCU @@ -436,6 +436,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -490,6 +496,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -529,6 +536,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -548,6 +557,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -670,4 +686,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBfindscu\fP(1), \fBstorescp\fP(1), \fBdump2dcm\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1994-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1994-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/pdf2dcm.1 b/doxygen/manpages/man1/pdf2dcm.1 index 9459d2ad..cd3bd500 100644 --- a/doxygen/manpages/man1/pdf2dcm.1 +++ b/doxygen/manpages/man1/pdf2dcm.1 @@ -1,4 +1,4 @@ -.TH "pdf2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "pdf2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME pdf2dcm \- Encapsulate PDF file into DICOM file format @@ -159,6 +159,31 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes .fi .PP +.SH "NOTES" +.PP +.SS "Attribute Sources" +The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information: +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be used to add further attributes to the DICOM output file\&. +.PP +.PD 0 +.IP "\(bu" 2 +It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&. +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be present more than once\&. +.PP +.PD 0 +.IP "\(bu" 2 +The value part (after the '=') may be absent causing the attribute to be set with zero length\&. +.PP +.PD 0 +.IP "\(bu" 2 +Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&. +.PP .SH "LOGGING" .PP The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&. @@ -206,4 +231,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcm2pdf\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2005-2018 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2005-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/stl2dcm.1 b/doxygen/manpages/man1/stl2dcm.1 index eab5b865..5e00f4b5 100644 --- a/doxygen/manpages/man1/stl2dcm.1 +++ b/doxygen/manpages/man1/stl2dcm.1 @@ -1,4 +1,4 @@ -.TH "stl2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "stl2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME stl2dcm \- Encapsulate STL file into DICOM file format @@ -179,6 +179,31 @@ data set trailing padding (not with --write-dataset): and items on multiple of i bytes .fi .PP +.SH "NOTES" +.PP +.SS "Attribute Sources" +The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information: +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be used to add further attributes to the DICOM output file\&. +.PP +.PD 0 +.IP "\(bu" 2 +It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&. +.PP +.PD 0 +.IP "\(bu" 2 +The \fI--key\fP option can be present more than once\&. +.PP +.PD 0 +.IP "\(bu" 2 +The value part (after the '=') may be absent causing the attribute to be set with zero length\&. +.PP +.PD 0 +.IP "\(bu" 2 +Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&. +.PP .SH "LOGGING" .PP The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&. @@ -223,4 +248,4 @@ The \fBstl2dcm\fP utility will attempt to load DICOM data dictionaries specified The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 2018 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2018-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/storescp.1 b/doxygen/manpages/man1/storescp.1 index 34430af0..b73b59c7 100644 --- a/doxygen/manpages/man1/storescp.1 +++ b/doxygen/manpages/man1/storescp.1 @@ -1,4 +1,4 @@ -.TH "storescp" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "storescp" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME storescp \- DICOM storage (C-STORE) SCP @@ -239,10 +239,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -379,6 +379,14 @@ data set trailing padding align file on multiple of f bytes and items on multiple of i bytes +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known + deflate compression level (only with --write-xfer-deflated/same): +cl --compression-level [l]evel: integer (default: 6) @@ -559,6 +567,12 @@ BasicVoiceAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4 GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2 ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1 RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1 +MultichannelRespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.2 +RoutineScalpElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.1 +ElectromyogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.2 +ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3 +SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4 +BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1 RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10 RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11 GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1 @@ -613,6 +627,7 @@ WideFieldOphthalmicPhotogr.3DCoordinatesImageStorage 1.2.840.10008.5.1.4.1.1.77. OphthalmicOpticalCoherenceTomogr.EnFaceImageStorage 1.2.840.10008.5.1.4.1.1.77.1.5.7 OphthalmicOpticalCoh.Tomogr.BscanVolumeAnalysisStor. 1.2.840.10008.5.1.4.1.1.77.1.5.8 VLWholeSlideMicroscopyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.6 +DermoscopicPhotographyImageStorage 1.2.840.10008.5.1.4.1.1.77.1.7 RETIRED_VLMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.77.2 LensometryMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.1 AutorefractionMeasurementsStorage 1.2.840.10008.5.1.4.1.1.78.2 @@ -652,6 +667,8 @@ ContentAssessmentResultsStorage 1.2.840.10008.5.1.4.1.1.90. EncapsulatedPDFStorage 1.2.840.10008.5.1.4.1.1.104.1 EncapsulatedCDAStorage 1.2.840.10008.5.1.4.1.1.104.2 EncapsulatedSTLStorage 1.2.840.10008.5.1.4.1.1.104.3 +EncapsulatedOBJStorage 1.2.840.10008.5.1.4.1.1.104.4 +EncapsulatedMTLStorage 1.2.840.10008.5.1.4.1.1.104.5 PositronEmissionTomographyImageStorage 1.2.840.10008.5.1.4.1.1.128 LegacyConvertedEnhancedPETImageStorage 1.2.840.10008.5.1.4.1.1.128.1 RETIRED_StandalonePETCurveStorage 1.2.840.10008.5.1.4.1.1.129 @@ -671,6 +688,13 @@ RTPhysicianIntentStorage 1.2.840.10008.5.1.4.1.1.481 RTSegmentAnnotationStorage 1.2.840.10008.5.1.4.1.1.481.11 RTRadiationSetStorage 1.2.840.10008.5.1.4.1.1.481.12 CArmPhotonElectronRadiationStorage 1.2.840.10008.5.1.4.1.1.481.13 +TomotherapeuticRadiationStorage 1.2.840.10008.5.1.4.1.1.481.14 +RoboticArmRadiationStorage 1.2.840.10008.5.1.4.1.1.481.15 +RTRadiationRecordSetStorage 1.2.840.10008.5.1.4.1.1.481.16 +RTRadiationSalvageRecordStorage 1.2.840.10008.5.1.4.1.1.481.17 +TomotherapeuticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.18 +CArmPhotonElectronRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.19 +RoboticRadiationRecordStorage 1.2.840.10008.5.1.4.1.1.481.20 DICOS_CTImageStorage 1.2.840.10008.5.1.4.1.1.501.1 DICOS_DigitalXRayImageStorageForPresentation 1.2.840.10008.5.1.4.1.1.501.2.1 DICOS_DigitalXRayImageStorageForProcessing 1.2.840.10008.5.1.4.1.1.501.2.2 @@ -771,4 +795,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBstorescu\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1996-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1996-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/storescu.1 b/doxygen/manpages/man1/storescu.1 index 64d9698b..ea845f84 100644 --- a/doxygen/manpages/man1/storescu.1 +++ b/doxygen/manpages/man1/storescu.1 @@ -1,4 +1,4 @@ -.TH "storescu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "storescu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME storescu \- DICOM storage (C-STORE) SCU @@ -321,10 +321,10 @@ key and certificate file format: certification authority: - +cf --add-cert-file [c]ertificate filename: string + +cf --add-cert-file [f]ilename: string add certificate file to list of certificates - +cd --add-cert-dir [c]ertificate directory: string + +cd --add-cert-dir [d]irectory: string add certificates in d to list of certificates security profile: @@ -513,4 +513,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBstorescp\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 1996-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1996-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/termscu.1 b/doxygen/manpages/man1/termscu.1 index 5b132adf..99cf267f 100644 --- a/doxygen/manpages/man1/termscu.1 +++ b/doxygen/manpages/man1/termscu.1 @@ -1,4 +1,4 @@ -.TH "termscu" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "termscu" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME termscu \- DICOM termination SCU diff --git a/doxygen/manpages/man1/wlmscpfs.1 b/doxygen/manpages/man1/wlmscpfs.1 index a7120931..3ae08498 100644 --- a/doxygen/manpages/man1/wlmscpfs.1 +++ b/doxygen/manpages/man1/wlmscpfs.1 @@ -1,4 +1,4 @@ -.TH "wlmscpfs" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "wlmscpfs" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME wlmscpfs \- DICOM Basic Worklist Management SCP (based on data files) @@ -97,12 +97,6 @@ other processing options: -nse --no-sq-expansion disable expansion of empty sequences in C-FIND request messages - - -rfp --request-file-path [p]ath: string - path to store request files to - - -rff --request-file-format [f]ormat: string (default: #t.dump) - request file name format .fi .PP .SS "network options" @@ -182,6 +176,18 @@ other network options: disable hostname lookup .fi .PP +.SS "output options" +.PP +.nf +general: + + -rfp --request-file-path [p]ath: string + path to store request files to + + -rff --request-file-format [f]ormat: string (default: #t.dump) + request file name format +.fi +.PP .SH "NOTES" .PP The semantic impacts of the above mentioned options is clear for the majority of options\&. Some particular options, however, are so specific that they need detailed descriptions which will be given in this passage\&. @@ -413,4 +419,4 @@ The \fBwlmscpfs\fP utility will attempt to load DICOM data dictionaries specifie The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&. .SH "COPYRIGHT" .PP -Copyright (C) 1996-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 1996-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/xml2dcm.1 b/doxygen/manpages/man1/xml2dcm.1 index 944114f0..a1c2974c 100644 --- a/doxygen/manpages/man1/xml2dcm.1 +++ b/doxygen/manpages/man1/xml2dcm.1 @@ -1,4 +1,4 @@ -.TH "xml2dcm" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "xml2dcm" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME xml2dcm \- Convert XML document to DICOM file or data set @@ -194,7 +194,7 @@ The basic structure of the XML input expected looks like the following: - 256\\0\\8 + 256\0\8 ... @@ -275,4 +275,4 @@ The default behavior should be preferred and the \fIDCMDICTPATH\fP environment v \fBdcm2xml\fP(1) .SH "COPYRIGHT" .PP -Copyright (C) 2003-2019 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. +Copyright (C) 2003-2021 e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&. diff --git a/doxygen/manpages/man1/xml2dsr.1 b/doxygen/manpages/man1/xml2dsr.1 index 1b008c35..79d5a614 100644 --- a/doxygen/manpages/man1/xml2dsr.1 +++ b/doxygen/manpages/man1/xml2dsr.1 @@ -1,4 +1,4 @@ -.TH "xml2dsr" 1 "Mon Oct 28 2019" "Version 3.6.5" "OFFIS DCMTK" \" -*- nroff -*- +.TH "xml2dsr" 1 "Thu Jan 14 2021" "Version 3.6.6" "OFFIS DCMTK" \" -*- nroff -*- .nh .SH NAME xml2dsr \- Convert XML document to DICOM SR file diff --git a/oflog/include/dcmtk/oflog/clogger.h b/oflog/include/dcmtk/oflog/clogger.h index 9508dd00..c8dba6bc 100644 --- a/oflog/include/dcmtk/oflog/clogger.h +++ b/oflog/include/dcmtk/oflog/clogger.h @@ -54,13 +54,13 @@ typedef int loglevel_t; #define L4CP_ALL_LOG_LEVEL TRACE_LOG_LEVEL #define L4CP_NOT_SET_LOG_LEVEL -1 -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE # define DCMTK_LOG4CPLUS_TEXT2(STRING) L##STRING typedef wchar_t log4cplus_char_t; #else # define DCMTK_LOG4CPLUS_TEXT2(STRING) STRING typedef char log4cplus_char_t; -#endif // UNICODE +#endif // DCMTK_OFLOG_UNICODE #define DCMTK_LOG4CPLUS_TEXT(STRING) DCMTK_LOG4CPLUS_TEXT2(STRING) DCMTK_LOG4CPLUS_EXPORT int log4cplus_file_configure(const log4cplus_char_t *pathname); diff --git a/oflog/include/dcmtk/oflog/config.h b/oflog/include/dcmtk/oflog/config.h index 835e7d24..8e21275c 100644 --- a/oflog/include/dcmtk/oflog/config.h +++ b/oflog/include/dcmtk/oflog/config.h @@ -40,7 +40,7 @@ # include "dcmtk/oflog/config/defines.h" #endif -#if ! defined (UNICODE) && ! defined (DCMTK_LOG4CPLUS_HAVE_VSNPRINTF_S) \ +#if ! defined (DCMTK_OFLOG_UNICODE) && ! defined (DCMTK_LOG4CPLUS_HAVE_VSNPRINTF_S) \ && ! defined (DCMTK_LOG4CPLUS_HAVE__VSNPRINTF_S) \ && ! defined (DCMTK_LOG4CPLUS_HAVE_VSNPRINTF) \ && ! defined (DCMTK_LOG4CPLUS_HAVE__VSNPRINTF) @@ -90,7 +90,7 @@ # define DCMTK_LOG4CPLUS_INLINE_EXPORT #endif -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) # if defined (_MSC_VER) && _MSC_VER >= 1400 # define DCMTK_LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T # endif @@ -118,7 +118,7 @@ # define DCMTK_LOG4CPLUS_HAVE_RVALUE_REFS #endif -#if ! defined (UNICODE) && defined (__GNUC__) && __GNUC__ >= 3 +#if ! defined (DCMTK_OFLOG_UNICODE) && defined (__GNUC__) && __GNUC__ >= 3 # define DCMTK_LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, format_index, first_arg_index) \ __attribute__ ((format (archetype, format_index, first_arg_index))) #else diff --git a/oflog/include/dcmtk/oflog/configrt.h b/oflog/include/dcmtk/oflog/configrt.h index e155c8b3..04956979 100644 --- a/oflog/include/dcmtk/oflog/configrt.h +++ b/oflog/include/dcmtk/oflog/configrt.h @@ -77,14 +77,14 @@ namespace log4cplus , fEncodingShift = 3 , fEncodingMask = 0x3 , fUnspecEncoding = (0 << fEncodingShift) -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (DCMTK_OFLOG_UNICODE) , fUTF8 = (1 << fEncodingShift) #endif #if (defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ - && defined (UNICODE) + && defined (DCMTK_OFLOG_UNICODE) , fUTF16 = (2 << fEncodingShift) #endif -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (DCMTK_OFLOG_UNICODE) , fUTF32 = (3 << fEncodingShift) #endif }; diff --git a/oflog/include/dcmtk/oflog/fstreams.h b/oflog/include/dcmtk/oflog/fstreams.h index 7b30bc18..136a531d 100644 --- a/oflog/include/dcmtk/oflog/fstreams.h +++ b/oflog/include/dcmtk/oflog/fstreams.h @@ -46,7 +46,7 @@ typedef STD_NAMESPACE basic_ifstream tifstream; //! \def DCMTK_LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) //! \brief Expands into expression that picks the right type for //! STD_NAMESPACE fstream file name parameter. -#if defined (DCMTK_LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T) && defined (DCMTK_OFLOG_UNICODE) # define DCMTK_LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (X) #else # define DCMTK_LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (DCMTK_LOG4CPLUS_TSTRING_TO_STRING(X)) diff --git a/oflog/include/dcmtk/oflog/helpers/property.h b/oflog/include/dcmtk/oflog/helpers/property.h index 3e42c4c7..7b0c941e 100644 --- a/oflog/include/dcmtk/oflog/helpers/property.h +++ b/oflog/include/dcmtk/oflog/helpers/property.h @@ -51,14 +51,14 @@ namespace log4cplus { fEncodingShift = 3 , fEncodingMask = 0x3 , fUnspecEncoding = (0 << fEncodingShift) -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (DCMTK_OFLOG_UNICODE) , fUTF8 = (1 << fEncodingShift) #endif #if (defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ - && defined (UNICODE) + && defined (DCMTK_OFLOG_UNICODE) , fUTF16 = (2 << fEncodingShift) #endif -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (DCMTK_OFLOG_UNICODE) , fUTF32 = (3 << fEncodingShift) #endif }; diff --git a/oflog/include/dcmtk/oflog/helpers/queue.h b/oflog/include/dcmtk/oflog/helpers/queue.h index 1ec0201d..f256df38 100644 --- a/oflog/include/dcmtk/oflog/helpers/queue.h +++ b/oflog/include/dcmtk/oflog/helpers/queue.h @@ -121,7 +121,7 @@ public: //! ERROR_BIT signals error. ERROR_BIT = 0x0010, - //! ERROR_AFTER signals error that has occured after queue has + //! ERROR_AFTER signals error that has occurred after queue has //! already been touched. ERROR_AFTER = 0x0020 }; diff --git a/oflog/include/dcmtk/oflog/socketap.h b/oflog/include/dcmtk/oflog/socketap.h index c107782a..9ec675e0 100644 --- a/oflog/include/dcmtk/oflog/socketap.h +++ b/oflog/include/dcmtk/oflog/socketap.h @@ -42,7 +42,7 @@ namespace log4cplus { -#ifndef UNICODE +#ifndef DCMTK_OFLOG_UNICODE size_t const DCMTK_LOG4CPLUS_MAX_MESSAGE_SIZE = 8*1024; #else size_t const DCMTK_LOG4CPLUS_MAX_MESSAGE_SIZE = 2*8*1024; diff --git a/oflog/include/dcmtk/oflog/streams.h b/oflog/include/dcmtk/oflog/streams.h index 4f6c5fb1..9f161e5e 100644 --- a/oflog/include/dcmtk/oflog/streams.h +++ b/oflog/include/dcmtk/oflog/streams.h @@ -49,7 +49,7 @@ namespace log4cplus } } -#if defined (UNICODE) && defined (DCMTK_LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) +#if defined (DCMTK_OFLOG_UNICODE) && defined (DCMTK_LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) DCMTK_LOG4CPLUS_EXPORT log4cplus::tostream& operator <<(log4cplus::tostream&, const char* psz ); diff --git a/oflog/include/dcmtk/oflog/tchar.h b/oflog/include/dcmtk/oflog/tchar.h index c3655d0e..643d52aa 100644 --- a/oflog/include/dcmtk/oflog/tchar.h +++ b/oflog/include/dcmtk/oflog/tchar.h @@ -38,11 +38,11 @@ #endif -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE # define DCMTK_LOG4CPLUS_TEXT2(STRING) L##STRING #else # define DCMTK_LOG4CPLUS_TEXT2(STRING) STRING -#endif // UNICODE +#endif // DCMTK_OFLOG_UNICODE #define DCMTK_LOG4CPLUS_TEXT(STRING) DCMTK_LOG4CPLUS_TEXT2(STRING) @@ -51,7 +51,7 @@ namespace dcmtk namespace log4cplus { -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) typedef wchar_t tchar; #else diff --git a/oflog/include/dcmtk/oflog/thread/impl/tls.h b/oflog/include/dcmtk/oflog/thread/impl/tls.h index 73718ad7..4ebaf806 100644 --- a/oflog/include/dcmtk/oflog/thread/impl/tls.h +++ b/oflog/include/dcmtk/oflog/thread/impl/tls.h @@ -49,22 +49,28 @@ #endif +#ifdef __MINGW32__ +/* MinGW does not support fiber local storage. Use Thread Local Storage instead. */ +#define DCMTK_LOG4CPLUS_AVOID_WIN32_FLS +#endif namespace dcmtk { namespace log4cplus { namespace thread { namespace impl { typedef void * tls_value_type; -typedef void (* tls_init_cleanup_func_type)(void *); #ifdef DCMTK_LOG4CPLUS_USE_PTHREADS typedef pthread_key_t * tls_key_type; +typedef void (* tls_init_cleanup_func_type)(void *); #elif defined (DCMTK_LOG4CPLUS_USE_WIN32_THREADS) typedef DWORD tls_key_type; +typedef void (WINAPI * tls_init_cleanup_func_type)(void *); #elif defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) typedef size_t tls_key_type; +typedef void (* tls_init_cleanup_func_type)(void *); #endif diff --git a/oflog/include/dcmtk/oflog/tstring.h b/oflog/include/dcmtk/oflog/tstring.h index 7ca173c4..d1c56abd 100644 --- a/oflog/include/dcmtk/oflog/tstring.h +++ b/oflog/include/dcmtk/oflog/tstring.h @@ -83,19 +83,19 @@ DCMTK_LOG4CPLUS_EXPORT STD_NAMESPACE wstring towstring(char const *); } // namespace helpers -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE #define DCMTK_LOG4CPLUS_C_STR_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) #define DCMTK_LOG4CPLUS_STRING_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) #define DCMTK_LOG4CPLUS_TSTRING_TO_STRING(STRING) log4cplus::helpers::tostring(STRING) -#else // UNICODE +#else // DCMTK_OFLOG_UNICODE #define DCMTK_LOG4CPLUS_C_STR_TO_TSTRING(STRING) OFString(STRING) #define DCMTK_LOG4CPLUS_STRING_TO_TSTRING(STRING) STRING #define DCMTK_LOG4CPLUS_TSTRING_TO_STRING(STRING) STRING -#endif // UNICODE +#endif // DCMTK_OFLOG_UNICODE } // namespace log4cplus } // end namespace dcmtk diff --git a/oflog/libsrc/config.cc b/oflog/libsrc/config.cc index 689eb5a1..c755d39d 100644 --- a/oflog/libsrc/config.cc +++ b/oflog/libsrc/config.cc @@ -183,18 +183,18 @@ namespace & (PropertyConfigurator::fEncodingMask << PropertyConfigurator::fEncodingShift)) { -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (DCMTK_OFLOG_UNICODE) case PropertyConfigurator::fUTF8: return helpers::Properties::fUTF8; #endif #if (defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (WIN32)) \ - && defined (UNICODE) + && defined (DCMTK_OFLOG_UNICODE) case PropertyConfigurator::fUTF16: return helpers::Properties::fUTF16; #endif -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (DCMTK_OFLOG_UNICODE) case PropertyConfigurator::fUTF32: return helpers::Properties::fUTF32; #endif diff --git a/oflog/libsrc/env.cc b/oflog/libsrc/env.cc index d8ffd584..b6030eda 100644 --- a/oflog/libsrc/env.cc +++ b/oflog/libsrc/env.cc @@ -46,7 +46,7 @@ namespace log4cplus { namespace internal { bool get_env_var (tstring & value, tstring const & name) { -#if defined (_WIN32) && defined (UNICODE) +#if defined (_WIN32) && defined (DCMTK_OFLOG_UNICODE) tchar const * val = _wgetenv (name.c_str ()); if (val) value = val; diff --git a/oflog/libsrc/fileap.cc b/oflog/libsrc/fileap.cc index 1e346159..7c5a2ee7 100644 --- a/oflog/libsrc/fileap.cc +++ b/oflog/libsrc/fileap.cc @@ -77,7 +77,7 @@ static long file_rename (tstring const & src, tstring const & target) { -#if defined (UNICODE) && defined (_WIN32) +#if defined (DCMTK_OFLOG_UNICODE) && defined (_WIN32) if (_wrename (src.c_str (), target.c_str ()) == 0) return 0; else @@ -98,7 +98,7 @@ static long file_remove (tstring const & src) { -#if defined (UNICODE) && defined (_WIN32) +#if defined (DCMTK_OFLOG_UNICODE) && defined (_WIN32) if (_wremove (src.c_str ()) == 0) return 0; else diff --git a/oflog/libsrc/fileinfo.cc b/oflog/libsrc/fileinfo.cc index b8cd1893..cb225681 100644 --- a/oflog/libsrc/fileinfo.cc +++ b/oflog/libsrc/fileinfo.cc @@ -48,8 +48,14 @@ getFileInfo (FileInfo * fi, tstring const & name) { #if defined (_WIN32) struct _stat fileStatus; + +#if defined (DCMTK_OFLOG_UNICODE) if (_tstat (name.c_str (), &fileStatus) == -1) return -1; +#else + if (_stat (name.c_str (), &fileStatus) == -1) + return -1; +#endif fi->mtime = helpers::Time (fileStatus.st_mtime); fi->is_link = false; diff --git a/oflog/libsrc/filter.cc b/oflog/libsrc/filter.cc index e9fd1e33..f027fb7c 100644 --- a/oflog/libsrc/filter.cc +++ b/oflog/libsrc/filter.cc @@ -137,9 +137,9 @@ LogLevelMatchFilter::decide(const InternalLoggingEvent& event) const return NEUTRAL; } - bool matchOccured = (logLevelToMatch == event.getLogLevel()); + bool matchOccurred = (logLevelToMatch == event.getLogLevel()); - if(matchOccured) { + if(matchOccurred) { return (acceptOnMatch ? ACCEPT : DENY); } else { diff --git a/oflog/libsrc/globinit.cc b/oflog/libsrc/globinit.cc index 8227e532..6da22c80 100644 --- a/oflog/libsrc/globinit.cc +++ b/oflog/libsrc/globinit.cc @@ -42,7 +42,7 @@ namespace dcmtk namespace log4cplus { -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE DCMTK_LOG4CPLUS_EXPORT tostream & tcout = STD_NAMESPACE wcout; DCMTK_LOG4CPLUS_EXPORT tostream & tcerr = STD_NAMESPACE wcerr; diff --git a/oflog/libsrc/log4judp.cc b/oflog/libsrc/log4judp.cc index 803fcb72..c79831ea 100644 --- a/oflog/libsrc/log4judp.cc +++ b/oflog/libsrc/log4judp.cc @@ -29,7 +29,7 @@ #include "dcmtk/oflog/thread/syncpub.h" #include #include -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) #include #else #include @@ -48,7 +48,7 @@ namespace static inline bool is_control (tchar ch) { -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) return !! STD_NAMESPACE iswcntrl (STD_NAMESPACE char_traits::to_int_type (ch)); #elif defined (_MSC_VER) && _MSC_VER <= 1200 /* MSC6 and older */ return !! iscntrl (STD_NAMESPACE char_traits::to_int_type (ch)); @@ -175,7 +175,7 @@ Log4jUdpAppender::~Log4jUdpAppender() // Log4jUdpAppender public methods ////////////////////////////////////////////////////////////////////////////// -void +void Log4jUdpAppender::close() { helpers::getLogLog().debug( diff --git a/oflog/libsrc/ntelogap.cc b/oflog/libsrc/ntelogap.cc index 6d009d5d..e3947535 100644 --- a/oflog/libsrc/ntelogap.cc +++ b/oflog/libsrc/ntelogap.cc @@ -46,7 +46,7 @@ namespace { static bool - copySID(SID** ppDstSid, SID* pSrcSid) + copySID(SID** ppDstSid, SID* pSrcSid) { DWORD dwLength = ::GetLengthSid(pSrcSid); @@ -68,8 +68,8 @@ namespace { static - bool - GetCurrentUserSID(SID** ppSid) + bool + GetCurrentUserSID(SID** ppSid) { bool bSuccess = false; TOKEN_USER * ptu = 0; @@ -102,44 +102,56 @@ namespace { static - HKEY + HKEY regGetKey(const tstring& subkey, DWORD* disposition) { HKEY hkey = 0; - RegCreateKeyEx(HKEY_LOCAL_MACHINE, - subkey.c_str(), - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_SET_VALUE, - NULL, - &hkey, +#if defined (DCMTK_OFLOG_UNICODE) + RegCreateKeyEx(HKEY_LOCAL_MACHINE, +#else + RegCreateKeyExA(HKEY_LOCAL_MACHINE, +#endif + subkey.c_str(), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + NULL, + &hkey, disposition); return hkey; } static - void + void regSetString(HKEY hkey, const tstring& name, const tstring& value) { - RegSetValueEx(hkey, - name.c_str(), - 0, - REG_SZ, +#if defined (DCMTK_OFLOG_UNICODE) + RegSetValueEx(hkey, +#else + RegSetValueExA(hkey, +#endif + name.c_str(), + 0, + REG_SZ, OFreinterpret_cast(BYTE const *, value.c_str()), OFstatic_cast(DWORD, value.length() * sizeof(tchar))); } static - void + void regSetDword(HKEY hkey, const tstring& name, DWORD value) { - RegSetValueEx(hkey, - name.c_str(), - 0, - REG_DWORD, +#if defined (DCMTK_OFLOG_UNICODE) + RegSetValueEx(hkey, +#else + RegSetValueExA(hkey, +#endif + name.c_str(), + 0, + REG_DWORD, OFreinterpret_cast(LPBYTE, &value), OFstatic_cast(DWORD, sizeof(DWORD))); } @@ -152,13 +164,13 @@ namespace { // NTEventLogAppender ctor and dtor ////////////////////////////////////////////////////////////////////////////// -NTEventLogAppender::NTEventLogAppender(const tstring& server, - const tstring& log, +NTEventLogAppender::NTEventLogAppender(const tstring& server, + const tstring& log, const tstring& source) -: server(server), - log(log), - source(source), - hEventLog(NULL), +: server(server), + log(log), + source(source), + hEventLog(NULL), pCurrentUserSID(NULL) { init(); @@ -171,7 +183,7 @@ NTEventLogAppender::NTEventLogAppender(const helpers::Properties & properties) server(properties.getProperty( DCMTK_LOG4CPLUS_TEXT("server") )), log(properties.getProperty( DCMTK_LOG4CPLUS_TEXT("log") )), source(properties.getProperty( DCMTK_LOG4CPLUS_TEXT("source") )), - hEventLog(NULL), + hEventLog(NULL), pCurrentUserSID(NULL) { init(); @@ -179,13 +191,13 @@ NTEventLogAppender::NTEventLogAppender(const helpers::Properties & properties) -void +void NTEventLogAppender::init() { if(source.empty()) { helpers::getLogLog().warn( DCMTK_LOG4CPLUS_TEXT("Source option not set for appender [") - + name + + name + DCMTK_LOG4CPLUS_TEXT("].")); return; } @@ -199,8 +211,13 @@ NTEventLogAppender::init() addRegistryInfo(); +#if defined (DCMTK_OFLOG_UNICODE) hEventLog = ::RegisterEventSource(server.empty () ? 0 : server.c_str(), source.c_str()); +#else + hEventLog = ::RegisterEventSourceA(server.empty () ? 0 : server.c_str(), + source.c_str()); +#endif if (! hEventLog || hEventLog == HANDLE(ERROR_INVALID_HANDLE)) helpers::getLogLog().warn ( DCMTK_LOG4CPLUS_TEXT("Event source registration failed.")); @@ -224,7 +241,7 @@ NTEventLogAppender::~NTEventLogAppender() // NTEventLogAppender public methods ////////////////////////////////////////////////////////////////////////////// -void +void NTEventLogAppender::close() { if(hEventLog != NULL) { @@ -240,7 +257,7 @@ NTEventLogAppender::close() // NTEventLogAppender protected methods ////////////////////////////////////////////////////////////////////////////// -void +void NTEventLogAppender::append(const spi::InternalLoggingEvent& event) { if(hEventLog == NULL) { @@ -256,7 +273,11 @@ NTEventLogAppender::append(const spi::InternalLoggingEvent& event) str.resize (31839); const tchar * s = str.c_str (); +#if defined (DCMTK_OFLOG_UNICODE) BOOL bSuccess = ::ReportEvent(hEventLog, +#else + BOOL bSuccess = ::ReportEventA(hEventLog, +#endif getEventType(event), getEventCategory(event), 0x1000, @@ -275,7 +296,7 @@ NTEventLogAppender::append(const spi::InternalLoggingEvent& event) -WORD +WORD NTEventLogAppender::getEventType(const spi::InternalLoggingEvent& event) { WORD ret_val; @@ -293,7 +314,7 @@ NTEventLogAppender::getEventType(const spi::InternalLoggingEvent& event) -WORD +WORD NTEventLogAppender::getEventCategory(const spi::InternalLoggingEvent& event) { WORD ret_val; @@ -317,28 +338,28 @@ NTEventLogAppender::getEventCategory(const spi::InternalLoggingEvent& event) // Add this source with appropriate configuration keys to the registry. -void +void NTEventLogAppender::addRegistryInfo() { DWORD disposition; HKEY hkey = 0; tstring subkey = DCMTK_LOG4CPLUS_TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\") - + log - + DCMTK_LOG4CPLUS_TEXT("\\") + + log + + DCMTK_LOG4CPLUS_TEXT("\\") + source; - + hkey = regGetKey(subkey, &disposition); if(disposition == REG_CREATED_NEW_KEY) { - regSetString(hkey, - DCMTK_LOG4CPLUS_TEXT("EventMessageFile"), + regSetString(hkey, + DCMTK_LOG4CPLUS_TEXT("EventMessageFile"), DCMTK_LOG4CPLUS_TEXT("NTEventLogAppender.dll")); - regSetString(hkey, - DCMTK_LOG4CPLUS_TEXT("CategoryMessageFile"), + regSetString(hkey, + DCMTK_LOG4CPLUS_TEXT("CategoryMessageFile"), DCMTK_LOG4CPLUS_TEXT("NTEventLogAppender.dll")); regSetDword(hkey, DCMTK_LOG4CPLUS_TEXT("TypesSupported"), OFstatic_cast(DWORD, 7)); regSetDword(hkey, DCMTK_LOG4CPLUS_TEXT("CategoryCount"), OFstatic_cast(DWORD, 5)); } - + RegCloseKey(hkey); return; } diff --git a/oflog/libsrc/property.cc b/oflog/libsrc/property.cc index 85b55d88..ba47a7d8 100644 --- a/oflog/libsrc/property.cc +++ b/oflog/libsrc/property.cc @@ -21,7 +21,7 @@ #include "dcmtk/oflog/config.h" #include -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) # include #else # include @@ -58,7 +58,7 @@ static int is_space (tchar ch) { -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) return STD_NAMESPACE iswspace (ch); #else return isspace (OFstatic_cast(unsigned char, ch)); @@ -133,7 +133,7 @@ Properties::Properties(const tstring& inputFile, unsigned flags) : data() switch (flags & fEncodingMask) { -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (DCMTK_OFLOG_UNICODE) case fUTF8: file.imbue ( STD_NAMESPACE locale (file.getloc (), @@ -142,7 +142,7 @@ Properties::Properties(const tstring& inputFile, unsigned flags) : data() break; #endif -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) && defined (DCMTK_OFLOG_UNICODE) case fUTF16: file.imbue ( STD_NAMESPACE locale (file.getloc (), @@ -150,7 +150,7 @@ Properties::Properties(const tstring& inputFile, unsigned flags) : data() OFstatic_cast(STD_NAMESPACE codecvt_mode, STD_NAMESPACE consume_header | STD_NAMESPACE little_endian)>)); break; -#elif defined (UNICODE) && defined (WIN32) +#elif defined (DCMTK_OFLOG_UNICODE) && defined (WIN32) case fUTF16: file.imbue ( STD_NAMESPACE locale (file.getloc (), @@ -159,7 +159,7 @@ Properties::Properties(const tstring& inputFile, unsigned flags) : data() #endif -#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) +#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (DCMTK_OFLOG_UNICODE) case fUTF32: file.imbue ( STD_NAMESPACE locale (file.getloc (), diff --git a/oflog/libsrc/snprintf.cc b/oflog/libsrc/snprintf.cc index bbf59cb2..7602942a 100644 --- a/oflog/libsrc/snprintf.cc +++ b/oflog/libsrc/snprintf.cc @@ -26,7 +26,7 @@ #include "dcmtk/oflog/internal/internal.h" #include #include -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) #include #endif #if defined (DCMTK_LOG4CPLUS_HAVE_STDARG_H) @@ -66,7 +66,7 @@ static inline int vftprintf (STD_NAMESPACE FILE * file, tchar const * fmt, va_list args) { -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) # if defined (DCMTK_LOG4CPLUS_HAVE_VFWPRINTF_S) return vfwprintf_s (file, fmt, args); # else @@ -92,7 +92,7 @@ vstprintf (tchar * dest, size_t dest_size, tchar const * fmt, va_list args) { int ret; -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) # if defined (DCMTK_LOG4CPLUS_HAVE_VSWPRINTF_S) ret = vswprintf_s (dest, dest_size, fmt, args); # else @@ -125,7 +125,7 @@ vsntprintf (tchar * dest, size_t dest_size, tchar const * fmt, { int ret; -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) # if defined (DCMTK_LOG4CPLUS_HAVE__VSNWPRINTF_S) && defined (_TRUNCATE) ret = _vsnwprintf_s (dest, dest_size, _TRUNCATE, fmt, args); # else diff --git a/oflog/libsrc/sockbuff.cc b/oflog/libsrc/sockbuff.cc index 52bb2506..f17bf4fd 100644 --- a/oflog/libsrc/sockbuff.cc +++ b/oflog/libsrc/sockbuff.cc @@ -150,7 +150,7 @@ SocketBuffer::readString(unsigned char sizeOfChar) strlen = bufferLen / sizeOfChar; } -#ifndef UNICODE +#ifndef DCMTK_OFLOG_UNICODE if(sizeOfChar == 1) { tstring ret(&buffer[pos], strlen); pos += strlen; @@ -168,7 +168,7 @@ SocketBuffer::readString(unsigned char sizeOfChar) getLogLog().error(DCMTK_LOG4CPLUS_TEXT("SocketBuffer::readString()- Invalid sizeOfChar!!!!")); } -#else /* UNICODE */ +#else /* DCMTK_OFLOG_UNICODE */ if(sizeOfChar == 1) { STD_NAMESPACE string ret(&buffer[pos], strlen); pos += strlen; @@ -252,7 +252,7 @@ SocketBuffer::appendString(const tstring& str) } appendInt(OFstatic_cast(unsigned, strlen)); -#ifndef UNICODE +#ifndef DCMTK_OFLOG_UNICODE memcpy(&buffer[pos], str.data(), strlen); pos += strlen; size = pos; diff --git a/oflog/libsrc/socketap.cc b/oflog/libsrc/socketap.cc index 6b9596aa..4e81da7e 100644 --- a/oflog/libsrc/socketap.cc +++ b/oflog/libsrc/socketap.cc @@ -276,7 +276,7 @@ convertToBuffer(SocketBuffer & buffer, const tstring& serverName) { buffer.appendByte(DCMTK_LOG4CPLUS_MESSAGE_VERSION); -#ifndef UNICODE +#ifndef DCMTK_OFLOG_UNICODE buffer.appendByte(1); #else buffer.appendByte(2); diff --git a/oflog/libsrc/strhelp.cc b/oflog/libsrc/strhelp.cc index ef1a3a51..859555b0 100644 --- a/oflog/libsrc/strhelp.cc +++ b/oflog/libsrc/strhelp.cc @@ -52,7 +52,7 @@ tstring const empty_str; // Global Methods ////////////////////////////////////////////////////////////////////////////// -#if defined (UNICODE) && defined (DCMTK_LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) +#if defined (DCMTK_OFLOG_UNICODE) && defined (DCMTK_LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) log4cplus::tostream& operator <<(log4cplus::tostream& stream, const char* str) @@ -171,7 +171,7 @@ struct toupper_func operator () (tchar ch) const { return STD_NAMESPACE char_traits::to_char_type ( -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE STD_NAMESPACE towupper #else toupper @@ -187,7 +187,7 @@ struct tolower_func operator () (tchar ch) const { return STD_NAMESPACE char_traits::to_char_type ( -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE STD_NAMESPACE towlower #else tolower diff --git a/oflog/libsrc/timehelp.cc b/oflog/libsrc/timehelp.cc index c36c0848..993f298e 100644 --- a/oflog/libsrc/timehelp.cc +++ b/oflog/libsrc/timehelp.cc @@ -29,7 +29,7 @@ #include #include #include -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) #include #endif @@ -69,7 +69,7 @@ const int ONE_SEC_IN_USEC = 1000000; using STD_NAMESPACE mktime; using STD_NAMESPACE gmtime; using STD_NAMESPACE localtime; -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) using STD_NAMESPACE wcsftime; #else using STD_NAMESPACE strftime; @@ -281,7 +281,7 @@ Time::getFormattedTime(const log4cplus::tstring& fmt_orig, bool use_gmtime) cons gft_sp.ret.reserve (OFstatic_cast(size_t, OFstatic_cast(double, gft_sp.fmt.size ()) * 1.35)); State state = TEXT; - // Walk the format string and process all occurences of %q and %Q. + // Walk the format string and process all occurrences of %q and %Q. for (log4cplus::tstring::const_iterator fmt_it = gft_sp.fmt.begin (); fmt_it != gft_sp.fmt.end (); ++fmt_it) @@ -368,7 +368,7 @@ Time::getFormattedTime(const log4cplus::tstring& fmt_orig, bool use_gmtime) cons { gft_sp.buffer.resize (buffer_size); errno = 0; -#ifdef UNICODE +#ifdef DCMTK_OFLOG_UNICODE len = wcsftime(&gft_sp.buffer[0], buffer_size, gft_sp.fmt.c_str(), &time); #else diff --git a/oflog/libsrc/winconap.cc b/oflog/libsrc/winconap.cc index e6269a87..45d2b44e 100644 --- a/oflog/libsrc/winconap.cc +++ b/oflog/libsrc/winconap.cc @@ -119,7 +119,7 @@ Win32ConsoleAppender::write_handle (void * outvoid, tchar const * s, size_t str_len) { HANDLE out = OFstatic_cast(HANDLE, outvoid); -#if defined (UNICODE) +#if defined (DCMTK_OFLOG_UNICODE) STD_NAMESPACE wstring wstr (s, str_len); STD_NAMESPACE string str (helpers::tostring (wstr)); str_len = str.size (); diff --git a/oflog/libsrc/windebap.cc b/oflog/libsrc/windebap.cc index acf564bc..47108a43 100644 --- a/oflog/libsrc/windebap.cc +++ b/oflog/libsrc/windebap.cc @@ -79,7 +79,11 @@ void Win32DebugAppender::append(const spi::InternalLoggingEvent& event) { const tchar * s = formatEvent (event).c_str(); +#if defined (DCMTK_OFLOG_UNICODE) ::OutputDebugString(s); +#else + ::OutputDebugStringA(s); +#endif } diff --git a/oflog/libsrc/winsock.cc b/oflog/libsrc/winsock.cc index f67fdb34..bf13596b 100644 --- a/oflog/libsrc/winsock.cc +++ b/oflog/libsrc/winsock.cc @@ -235,9 +235,15 @@ connectSocket(const tstring& hostn, unsigned short port, bool udp, SocketState& { insock.sin_family = AF_INET; INT insock_size = OFstatic_cast(int, sizeof (insock)); +#if defined (DCMTK_OFLOG_UNICODE) INT ret = WSAStringToAddress (OFconst_cast(LPTSTR, hostn.c_str ()), AF_INET, 0, OFreinterpret_cast(struct sockaddr *, &insock), &insock_size); +#else + INT ret = WSAStringToAddressA (OFconst_cast(LPSTR, hostn.c_str ()), + AF_INET, 0, OFreinterpret_cast(struct sockaddr *, &insock), + &insock_size); +#endif if (ret == SOCKET_ERROR || insock_size != sizeof (insock)) { state = bad_address; diff --git a/ofstd/include/dcmtk/ofstd/ofdatime.h b/ofstd/include/dcmtk/ofstd/ofdatime.h index 4a974b4a..b00b5de9 100644 --- a/ofstd/include/dcmtk/ofstd/ofdatime.h +++ b/ofstd/include/dcmtk/ofstd/ofdatime.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2017, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -34,7 +34,10 @@ * class declaration * *---------------------*/ -/** This class is a combination of OFDate and OFTime +/** This class is a combination of OFDate and OFTime. + * @note Please note that support for the leap second is limited: a value of + * 60 seconds is accepted (i.e. regarded as valid) but calculations based on + * such a time value might be incorrect. */ class DCMTK_OFSTD_EXPORT OFDateTime { diff --git a/ofstd/include/dcmtk/ofstd/ofexit.h b/ofstd/include/dcmtk/ofstd/ofexit.h index a315a256..6f220d30 100644 --- a/ofstd/include/dcmtk/ofstd/ofexit.h +++ b/ofstd/include/dcmtk/ofstd/ofexit.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2018, OFFIS e.V. + * Copyright (C) 2018-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -36,6 +36,8 @@ #define EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 #define EXITCODE_INSUFFICIENT_PRIVILEGES 2 #define EXITCODE_SETUID_FAILED 3 +#define EXITCODE_MEMORY_EXHAUSTED 4 +#define EXITCODE_NOOPENSSL 5 // input file errors (20-39) #define EXITCODE_CANNOT_READ_INPUT_FILE 20 @@ -54,7 +56,7 @@ // processing errors (80-99) // - defined in the respective modules / tools -// user-defined errors (100-119) +// application-specific or user-defined errors (100-127) // - defined in the respective modules / tools // GNU recommends that the codes 128-255 be reserved for serious errors: diff --git a/ofstd/include/dcmtk/ofstd/offile.h b/ofstd/include/dcmtk/ofstd/offile.h index 7ef3fc9e..6446e0af 100644 --- a/ofstd/include/dcmtk/ofstd/offile.h +++ b/ofstd/include/dcmtk/ofstd/offile.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2006-2019, OFFIS e.V. + * Copyright (C) 2006-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -131,7 +131,7 @@ public: /** constructor expecting a conventional character string * @param filename filename to be stored (8-bit characters, e.g. UTF-8) * @param convert convert given filename to wide character encoding as an - * alternative representation + * alternative representation. Only works on Windows systems. */ OFFilename(const char *filename, const OFBool convert = OFFalse); @@ -144,18 +144,20 @@ public: OFFilename(const OFString &filename, const OFBool convert = OFFalse); - /** construct an OFFilename from an OFpath. - * @param path the OFpath object referring to a file. - * Effectively OFFilename(path.native(), OFTrue), but potentially more - * efficient. + /** constructor expecting an OFpath instance + * @param path OFpath instance storing a filename in native format + * (currently, identical to an 8-bit character string) + * @param convert convert given filename to wide character encoding as an + * alternative representation. Only works on Windows systems. */ - OFFilename(const OFpath& path); + OFFilename(const OFpath &path, + const OFBool convert = OFFalse); #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) /** constructor expecting a wide character string * @remark This constructor is only available if DCMTK is compiled on Windows - * Operating Systems with wide chars enabled (defining _WIN32 as well as - * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). + * Operating Systems with wide chars enabled (defining _WIN32 as well as + * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). * @param filename filename to be stored (e.g. 16-bit characters) * @param convert convert given filename to UTF-8 encoding as an * alternative representation. Only works on Windows systems. @@ -217,8 +219,8 @@ public: #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) /** get stored filename consisting of wide characters * @remark This method is only available if DCMTK is compiled on Windows - * Operating Systems with wide chars enabled (defining _WIN32 as well as - * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). + * Operating Systems with wide chars enabled (defining _WIN32 as well as + * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). * @return wide char filename (might be NULL if none is stored) */ inline const wchar_t *getWideCharPointer() const @@ -243,11 +245,20 @@ public: void set(const OFString &filename, const OFBool convert = OFFalse); + /** replace currently stored filename by given value + * @param OFpath OFpath instance storing a filename in native format + * (currently, identical to an 8-bit character string) + * @param convert convert given filename to wide character encoding as an + * alternative representation). Only works on Windows systems. + */ + void set(const OFpath &path, + const OFBool convert = OFFalse); + #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) /** replace currently stored filename by given value * @remark This method is only available if DCMTK is compiled on Windows - * Operating Systems with wide chars enabled (defining _WIN32 as well as - * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). + * Operating Systems with wide chars enabled (defining _WIN32 as well as + * WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). * @param filename filename to be stored (e.g. 16-bit characters) * @param convert convert given filename to UTF-8 encoding as an alternative * representation. Only works on Windows systems. @@ -258,12 +269,12 @@ public: private: /// filename consisting of conventional characters (8-bit, e.g.\ UTF-8) - /// @remark This member is only available if DCMTK is compiled on Windows - /// Operating Systems with wide chars enabled (defining _WIN32 as well as - /// WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). char *filename_; #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) /// filename consisting of wide characters (e.g. 16-bit on Windows) + /// @remark This member is only available if DCMTK is compiled on Windows + /// Operating Systems with wide chars enabled (defining _WIN32 as well as + /// WIDE_CHAR_FILE_IO_FUNCTIONS or WIDE_CHAR_MAIN_FUNCTION). wchar_t *wfilename_; #endif }; @@ -341,8 +352,8 @@ public: /** opens the file whose name is the wide character string pointed to by path and * associates a stream with it. * @remark This member is only available if DCMTK is compiled on Windows - * Operating Systems with wide chars enabled (defining _WIN32 as well as - * WIDE_CHAR_FILE_IO_FUNCTIONS). + * Operating Systems with wide chars enabled (defining _WIN32 as well as + * WIDE_CHAR_FILE_IO_FUNCTIONS). * @param filename Unicode filename path to file * @param modes "r", "w" or "a" with possible modifiers "+", "b", as a wide * character string diff --git a/ofstd/include/dcmtk/ofstd/oflimits.h b/ofstd/include/dcmtk/ofstd/oflimits.h index 50e5e125..13f731b5 100644 --- a/ofstd/include/dcmtk/ofstd/oflimits.h +++ b/ofstd/include/dcmtk/ofstd/oflimits.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2014-2017, OFFIS e.V. + * Copyright (C) 2014-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -983,7 +983,6 @@ struct OFnumeric_limits static inline T denorm_min() { return T(); } }; -#ifdef HAVE_CXX_BOOL template<> struct OFnumeric_limits { @@ -1020,7 +1019,6 @@ struct OFnumeric_limits static inline bool signaling_NaN() { return OFFalse; } static inline bool denorm_min() { return OFFalse; } }; -#endif template<> struct OFnumeric_limits diff --git a/ofstd/include/dcmtk/ofstd/ofmap.h b/ofstd/include/dcmtk/ofstd/ofmap.h index bcc07ba1..7a425277 100644 --- a/ofstd/include/dcmtk/ofstd/ofmap.h +++ b/ofstd/include/dcmtk/ofstd/ofmap.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2009-2017, OFFIS e.V. + * Copyright (C) 2009-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -209,11 +209,25 @@ public: */ OFPair insert(const value_type& val) { + // If value already exists, return it OFListIterator(value_type) it = find(val.first); if (it != end()) return OFMake_pair(it, false); - it = values_.insert(values_.end(), val); + // Sorted insertion + it = begin(); + while ( (it != end()) && (val.first > it->first) ) + it++; + if (it == end()) + it = values_.insert(values_.end(), val); + else + { + // Insert at current position and rewind iterator + // to the inserted element + values_.insert(it, val); + it--; + } + return OFMake_pair(it, true); } diff --git a/ofstd/include/dcmtk/ofstd/oftest.h b/ofstd/include/dcmtk/ofstd/oftest.h index 0eb070b7..18b0b5f3 100644 --- a/ofstd/include/dcmtk/ofstd/oftest.h +++ b/ofstd/include/dcmtk/ofstd/oftest.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2012, OFFIS e.V. + * Copyright (C) 2011-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This code is inspired by quicktest. @@ -207,7 +207,7 @@ public: return 254; } - return numFailed; + return OFstatic_cast(int, numFailed); } /** Handle the given arguments and run the requested test case. This diff --git a/ofstd/include/dcmtk/ofstd/oftime.h b/ofstd/include/dcmtk/ofstd/oftime.h index cfeb3d4c..bcc62133 100644 --- a/ofstd/include/dcmtk/ofstd/oftime.h +++ b/ofstd/include/dcmtk/ofstd/oftime.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2011, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -41,7 +41,10 @@ END_EXTERN_C * class declaration * *---------------------*/ -/** This class provides a collection of time functions +/** This class provides a collection of time functions. + * @note Please note that support for the leap second is limited: a value of + * 60 seconds is accepted (i.e. regarded as valid) but calculations based on + * such a time value might be incorrect. */ class DCMTK_OFSTD_EXPORT OFTime { @@ -138,8 +141,8 @@ class DCMTK_OFSTD_EXPORT OFTime virtual void clear(); /** check whether the currently stored time value is valid. - * Valid ranges: [0,24[ for 'hour', [0,60[ for 'minute', [0.0,60.0[ for 'second' - * and [-12.0,+14.0] for 'timeZone' + * Valid ranges: [0,24[ for 'hour', [0,60[ for 'minute', [0.0,60.0] for 'second' + * (including leap second) and [-12.0,+14.0] for 'timeZone' * @return OFTrue if the current value is valid, OFFalse otherwise */ virtual OFBool isValid() const; diff --git a/ofstd/include/dcmtk/ofstd/oftraits.h b/ofstd/include/dcmtk/ofstd/oftraits.h index 3e8f7755..65081d8c 100644 --- a/ofstd/include/dcmtk/ofstd/oftraits.h +++ b/ofstd/include/dcmtk/ofstd/oftraits.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2014-2017, OFFIS e.V. + * Copyright (C) 2014-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -138,10 +138,8 @@ struct OFremove_volatile { typedef T type; }; template struct OFremove_extent { typedef T type; }; -#ifdef HAVE_CXX_BOOL template<> struct OFis_unsigned : OFtrue_type {}; -#endif #ifndef C_CHAR_UNSIGNED template<> diff --git a/ofstd/include/dcmtk/ofstd/oftypes.h b/ofstd/include/dcmtk/ofstd/oftypes.h index 63eef5ad..436daa03 100644 --- a/ofstd/include/dcmtk/ofstd/oftypes.h +++ b/ofstd/include/dcmtk/ofstd/oftypes.h @@ -163,30 +163,10 @@ typedef Uint64 OFuintptr_t; // Definition of type OFBool -#ifdef HAVE_CXX_BOOL - -#define OFBool bool +typedef bool OFBool; #define OFTrue true #define OFFalse false -#else - -/** the boolean type used throughout the DCMTK project. Mapped to the - * built-in type "bool" if the current C++ compiler supports it. Mapped - * to int for old-fashioned compilers which do not yet support bool. - */ -typedef int OFBool; - -#ifndef OFTrue -#define OFTrue (1) -#endif - -#ifndef OFFalse -#define OFFalse (0) -#endif - -#endif - #if defined(HAVE_TYPENAME) #define OFTypename typename #else diff --git a/ofstd/include/dcmtk/ofstd/ofxml.h b/ofstd/include/dcmtk/ofstd/ofxml.h index f74dac8f..06d2e85a 100644 --- a/ofstd/include/dcmtk/ofstd/ofxml.h +++ b/ofstd/include/dcmtk/ofstd/ofxml.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2019, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were slightly modified by @@ -78,9 +78,8 @@ * full-fledged HTML documentation using the DOXYGEN software: simply type: "doxygen doxy.cfg" * * By default, the XMLParser library uses (char*) for string representation.To use the (wchar_t*) - * version of the library, you need to define the "_UNICODE" preprocessor definition variable - * (this is usually done inside your project definition file) (This is done automatically for you - * when using Visual Studio). + * version of the library, you need to define the "WIDE_CHAR_XML_PARSER" preprocessor definition variable + * (this is usually done inside your project definition file) * * \section example Advanced Tutorial and Many Examples of usage. * @@ -144,13 +143,9 @@ #include "dcmtk/ofstd/ofstdinc.h" #include "dcmtk/ofstd/ofdefine.h" -// DCMTK: we might want to enable wide characters without the "official" defines -#if defined(UNICODE) || defined(_UNICODE) || defined(WIDE_CHAR_XML_PARSER) -// If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters). -// This is useful when you get error messages like: -// 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *' -// The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the preprocessor variable -// must be defined) or utf8-mode (the pre-processor variable must be undefined). +// DCMTK: The XML parser is compiled in wide char (UTF-16) mode if and only if this macro is defined. +// We want this to be independent from the UNICODE/_UNICODE macros. +#ifdef WIDE_CHAR_XML_PARSER #define _XMLWIDECHAR #endif diff --git a/ofstd/libsrc/Makefile.dep b/ofstd/libsrc/Makefile.dep index c90c7870..ad85ec11 100644 --- a/ofstd/libsrc/Makefile.dep +++ b/ofstd/libsrc/Makefile.dep @@ -6,14 +6,10 @@ ofchrenc.o: ofchrenc.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/ofmem.h \ ../include/dcmtk/ofstd/ofutil.h ../include/dcmtk/ofstd/oftraits.h \ ../include/dcmtk/ofstd/variadic/tuplefwd.h \ - ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ + ../include/dcmtk/ofstd/ofthread.h ../include/dcmtk/ofstd/ofstd.h \ + ../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/oflimits.h \ ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofdiag.h \ - ../include/dcmtk/ofstd/ofconsol.h ../include/dcmtk/ofstd/ofthread.h \ - ../include/dcmtk/ofstd/diag/push.def \ - ../include/dcmtk/ofstd/diag/shadow.def \ - ../include/dcmtk/ofstd/diag/pop.def + ../include/dcmtk/ofstd/ofconsol.h ofcmdln.o: ofcmdln.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofcmdln.h ../include/dcmtk/ofstd/oftypes.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ @@ -23,10 +19,9 @@ ofcmdln.o: ofcmdln.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/ofconsol.h \ ../include/dcmtk/ofstd/ofthread.h ../include/dcmtk/ofstd/offile.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofchrenc.h \ - ../include/dcmtk/ofstd/ofmem.h ../include/dcmtk/ofstd/ofutil.h \ + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h \ + ../include/dcmtk/ofstd/ofchrenc.h ../include/dcmtk/ofstd/ofmem.h \ + ../include/dcmtk/ofstd/ofutil.h \ ../include/dcmtk/ofstd/variadic/tuplefwd.h ofconapp.o: ofconapp.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofconapp.h ../include/dcmtk/ofstd/oftypes.h \ @@ -38,11 +33,7 @@ ofconapp.o: ofconapp.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofconsol.h ../include/dcmtk/ofstd/ofthread.h \ ../include/dcmtk/ofstd/offile.h ../include/dcmtk/ofstd/ofstd.h \ ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofexit.h \ - ../include/dcmtk/ofstd/ofchrenc.h ../include/dcmtk/ofstd/ofmem.h \ - ../include/dcmtk/ofstd/ofutil.h \ - ../include/dcmtk/ofstd/variadic/tuplefwd.h + ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofexit.h ofcond.o: ofcond.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/oftypes.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ @@ -82,7 +73,6 @@ oferror.o: oferror.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftraits.h \ ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofdiag.h \ ../include/dcmtk/ofstd/diag/push.def \ ../include/dcmtk/ofstd/diag/vsprfw.def \ @@ -94,11 +84,11 @@ offile.o: offile.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofstring.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/offilsys.h \ - ../include/dcmtk/ofstd/ofmem.h ../include/dcmtk/ofstd/ofutil.h \ - ../include/dcmtk/ofstd/variadic/tuplefwd.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h \ + ../include/dcmtk/ofstd/offilsys.h ../include/dcmtk/ofstd/ofmem.h \ + ../include/dcmtk/ofstd/ofutil.h \ + ../include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/ofstd/ofthread.h offilsys.o: offilsys.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstdinc.h ../include/dcmtk/ofstd/offilsys.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftypes.h \ @@ -106,7 +96,8 @@ offilsys.o: offilsys.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/ofstd/ofmem.h ../include/dcmtk/ofstd/ofutil.h \ ../include/dcmtk/ofstd/oftraits.h \ - ../include/dcmtk/ofstd/variadic/tuplefwd.h + ../include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/ofstd/ofthread.h offname.o: offname.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/offname.h ../include/dcmtk/ofstd/oftypes.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ @@ -114,9 +105,7 @@ offname.o: offname.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofstring.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h oflist.o: oflist.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/oftypes.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ @@ -135,9 +124,7 @@ ofrand.o: ofrand.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofstd.h \ ../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/ofstring.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h ofsockad.o: ofsockad.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofsockad.h ../include/dcmtk/ofstd/ofdefine.h \ ../include/dcmtk/ofstd/ofcast.h ../include/dcmtk/ofstd/ofexport.h \ @@ -149,7 +136,6 @@ ofstd.o: ofstd.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstdinc.h ../include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftraits.h \ ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/offile.h \ ../include/dcmtk/ofstd/oftuple.h ../include/dcmtk/ofstd/ofutil.h \ ../include/dcmtk/ofstd/variadic/tuplefwd.h \ @@ -168,9 +154,7 @@ ofstring.o: ofstring.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofbmanip.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h ofstrutl.o: ofstrutl.cc ../include/dcmtk/ofstd/ofstrutl.h \ ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftypes.h \ @@ -185,17 +169,12 @@ oftempf.o: oftempf.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/offname.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ ../include/dcmtk/ofstd/oferror.h ofthread.o: ofthread.cc ../../config/include/dcmtk/config/osconfig.h \ - ../include/dcmtk/ofstd/ofstdinc.h ../include/dcmtk/ofstd/ofstd.h \ - ../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/oftypes.h \ + ../include/dcmtk/ofstd/ofthread.h ../include/dcmtk/ofstd/oftypes.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ - ../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstream.h \ - ../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftraits.h \ - ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofstring.h \ ../include/dcmtk/ofstd/ofconsol.h oftime.o: oftime.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofstdinc.h ../include/dcmtk/ofstd/oftime.h \ @@ -204,9 +183,7 @@ oftime.o: oftime.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h oftimer.o: oftimer.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/oftimer.h ../include/dcmtk/ofstd/ofstream.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ @@ -219,9 +196,7 @@ ofuuid.o: ofuuid.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofrand.h ../include/dcmtk/ofstd/ofthread.h \ ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/oflist.h \ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/ofcond.h \ - ../include/dcmtk/ofstd/oflimits.h \ - ../../config/include/dcmtk/config/arith.h \ - ../include/dcmtk/ofstd/oferror.h + ../include/dcmtk/ofstd/oflimits.h ../include/dcmtk/ofstd/oferror.h ofxml.o: ofxml.cc ../../config/include/dcmtk/config/osconfig.h \ ../include/dcmtk/ofstd/ofxml.h ../include/dcmtk/ofstd/ofstdinc.h \ ../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \ diff --git a/ofstd/libsrc/offile.cc b/ofstd/libsrc/offile.cc index fb34332f..82584188 100644 --- a/ofstd/libsrc/offile.cc +++ b/ofstd/libsrc/offile.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2016, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -25,6 +25,7 @@ #include "dcmtk/ofstd/offile.h" #include "dcmtk/ofstd/offilsys.h" +#include "dcmtk/ofstd/ofutil.h" #ifdef HAVE_WINDOWS_H #include "dcmtk/ofstd/ofchrenc.h" /* for class OFCharacterEncoding */ @@ -61,13 +62,14 @@ OFFilename::OFFilename(const OFString &filename, set(filename, convert); } -OFFilename::OFFilename(const OFpath &path) +OFFilename::OFFilename(const OFpath &path, + const OFBool convert) : filename_(NULL) #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) , wfilename_(NULL) #endif { - set(path.native(), OFTrue); + set(path, convert); } #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) @@ -130,13 +132,9 @@ void OFFilename::clear() void OFFilename::swap(OFFilename &arg) { - char *charPointer = filename_; - filename_ = arg.filename_; - arg.filename_ = charPointer; + OFswap(filename_, arg.filename_); #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) - wchar_t *wideCharPointer = wfilename_; - wfilename_ = arg.wfilename_; - arg.wfilename_ = wideCharPointer; + OFswap(wfilename_, arg.wfilename_); #endif } @@ -186,6 +184,13 @@ void OFFilename::set(const OFString &filename, } +void OFFilename::set(const OFpath &path, + const OFBool convert) +{ + set(path.native(), convert); +} + + #if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32) void OFFilename::set(const wchar_t *filename, const OFBool convert) diff --git a/ofstd/libsrc/ofstd.cc b/ofstd/libsrc/ofstd.cc index 3986939a..2ee83427 100644 --- a/ofstd/libsrc/ofstd.cc +++ b/ofstd/libsrc/ofstd.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2001-2019, OFFIS e.V. + * Copyright (C) 2001-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -471,7 +471,7 @@ OFBool OFStandard::fileExists(const OFFilename &fileName) fileAttr = GetFileAttributesW(fileName.getWideCharPointer()); else #endif - fileAttr = GetFileAttributes(fileName.getCharPointer()); + fileAttr = GetFileAttributesA(fileName.getCharPointer()); if (fileAttr != 0xffffffff) { /* check file type (not a directory?) */ @@ -501,7 +501,7 @@ OFBool OFStandard::dirExists(const OFFilename &dirName) fileAttr = GetFileAttributesW(dirName.getWideCharPointer()); else #endif - fileAttr = GetFileAttributes(dirName.getCharPointer()); + fileAttr = GetFileAttributesA(dirName.getCharPointer()); if (fileAttr != 0xffffffff) { /* check file type (is a directory?) */ @@ -1875,6 +1875,7 @@ double OFStandard::atof(const char *s, OFBool *success) int expSign = 0; double fraction; int exponent = 0; // Exponent read from "EX" field. + int old_exponent = 0; const char *pExp; // Temporarily holds location of exponent in string. /* Exponent that derives from the fractional part. Under normal @@ -2000,8 +2001,24 @@ double OFStandard::atof(const char *s, OFBool *success) } while (isdigit(OFstatic_cast(unsigned char, *p))) { + old_exponent = exponent; exponent = exponent * 10 + (*p - '0'); ++p; + if (exponent < old_exponent) + { + // overflow of the exponent. We cannot represent this number in an integer + // and also not in a double, where the exponent must not be larger than 308. + if (expSign) + { + // negative exponent. return 0 and leave success flag set to false + return 0.0; + } + else + { + // positive exponent. return plus/minus HUGE_VAL, depending on the sign bit + if (sign) return -HUGE_VAL; else return HUGE_VAL; + } + } } } diff --git a/ofstd/libsrc/ofstring.cc b/ofstd/libsrc/ofstring.cc index d537315d..1e8674a0 100644 --- a/ofstd/libsrc/ofstring.cc +++ b/ofstd/libsrc/ofstring.cc @@ -24,7 +24,7 @@ ** A simple string class ** - for OFFIS projects when an ANSI string class is not always available ** - based on the ANSI-C++ specifications -** - this impementation is intended to be slow but reliable +** - this implementation is intended to be slow but reliable ** - it is known to be slow but is it reliable? */ @@ -527,7 +527,7 @@ OFString::find (const OFString& pattern, size_t pos) const return OFString_npos; } for (size_t i = pos; i < this_size; i++) { - /* is there enought space for the pattern? */ + /* is there enough space for the pattern? */ if ((i + pattern_size) > this_size) { return OFString_npos; } diff --git a/ofstd/libsrc/oftempf.cc b/ofstd/libsrc/oftempf.cc index 9fd23db6..a3761f7c 100644 --- a/ofstd/libsrc/oftempf.cc +++ b/ofstd/libsrc/oftempf.cc @@ -128,7 +128,7 @@ void OFTempFile::getTempPath(OFString& sPath) #ifdef _WIN32 #define BUFFER_SIZE 1024 char buffer[BUFFER_SIZE]; - GetTempPath(BUFFER_SIZE, buffer); + GetTempPathA(BUFFER_SIZE, buffer); sPath = buffer; #elif defined(__ANDROID__) sPath = ANDROID_TEMPORARY_FILES_LOCATION; diff --git a/ofstd/libsrc/oftime.cc b/ofstd/libsrc/oftime.cc index 75099d2b..72941e17 100644 --- a/ofstd/libsrc/oftime.cc +++ b/ofstd/libsrc/oftime.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2018, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -191,8 +191,8 @@ OFBool OFTime::isTimeValid(const unsigned int hour, const double second, const double timeZone) { - /* check whether given time is valid */ - return (hour < 24) && (minute < 60) && (second >= 0) && (second < 60) && (timeZone >= -12) && (timeZone <= 14); + /* check whether given time is valid (also support leap second) */ + return (hour < 24) && (minute < 60) && (second >= 0) && (second <= 60) && (timeZone >= -12) && (timeZone <= 14); } @@ -287,7 +287,7 @@ OFBool OFTime::setTimeInSeconds(const double seconds, const OFBool normalize) { OFBool status = OFFalse; - /* only change if the new time is valid */ + /* only change if the new time is valid (leap second is not supported!) */ if (normalize || ((seconds >= 0) && (seconds < 86400))) { /* first normalize the value first to the valid range of [0.0,86400.0[ */ diff --git a/ofstd/tests/tatof.cc b/ofstd/tests/tatof.cc index 5da97cd2..b0cf04c7 100644 --- a/ofstd/tests/tatof.cc +++ b/ofstd/tests/tatof.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 1997-2014, OFFIS e.V. + * Copyright (C) 1997-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -69,10 +69,9 @@ const ValuePair vp[] = // overflow is reported as infinity {"1.7976931348623157E+1000", HUGE_VAL, OFTrue}, -#if !defined(_MSC_VER) || _MSC_VER >= 1700 - // underflow is reported as zero - {"2.2250738585072014E-1000", 0.0, OFTrue}, -#endif + // underflow should be reported as zero, but on some platforms that support + // denormalized floating point numbers this test case fails. + // {"2.2250738585072014E-1000", 0.0, OFTrue}, {"NaN", OFnumeric_limits::quiet_NaN(), OFTrue}, {"INF", OFnumeric_limits::infinity(), OFTrue}, diff --git a/ofstd/tests/tests.cc b/ofstd/tests/tests.cc index a419911b..1cf9ef06 100644 --- a/ofstd/tests/tests.cc +++ b/ofstd/tests/tests.cc @@ -23,6 +23,7 @@ #define OFTEST_OFSTD_ONLY #include "dcmtk/ofstd/oftest.h" +#include "dcmtk/ofstd/ofxml.h" OFTEST_REGISTER(ofstd_OFCharacterEncoding_1); OFTEST_REGISTER(ofstd_OFCharacterEncoding_2); @@ -72,7 +73,9 @@ OFTEST_REGISTER(ofstd_testPaths_2); #ifdef WITH_THREADS OFTEST_REGISTER(ofstd_thread); #endif // WITH_THREADS +#ifndef _XMLWIDECHAR OFTEST_REGISTER(ofstd_xmlParser); +#endif OFTEST_REGISTER(ofstd_memory); OFTEST_REGISTER(ofstd_optional); OFTEST_REGISTER(ofstd_tuple); diff --git a/ofstd/tests/tmap.cc b/ofstd/tests/tmap.cc index f0216085..150ae65b 100644 --- a/ofstd/tests/tmap.cc +++ b/ofstd/tests/tmap.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2009-2011, OFFIS e.V. + * Copyright (C) 2009-2019, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -71,4 +71,18 @@ OFTEST(ofstd_OFMap) OFCHECK_EQUAL(m.size(), 2); OFCHECK_EQUAL(m[3], 3); + + // Check whether map is sorted + m.clear(); + // Insert values in reverse order + for (i = 0; i < 6 ; ++i) + m[6 - i] = 6 - i; + // Check all elements are stored in sorted order + OFCHECK_EQUAL(m.size(), 6); + it = m.begin(); + for (i = 1; i <= 6; ++i) + { + OFCHECK((*it).second == i); + it++; + } } diff --git a/ofstd/tests/tofdatim.cc b/ofstd/tests/tofdatim.cc index f18250cc..4ea801ee 100644 --- a/ofstd/tests/tofdatim.cc +++ b/ofstd/tests/tofdatim.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2002-2017, OFFIS e.V. + * Copyright (C) 2002-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -97,6 +97,10 @@ OFTEST(ofstd_OFTime) OFCHECK_EQUAL(time1.getTimeZone(), -9.75); OFCHECK(time1.setISOFormattedTime("12:15:30 +09:15")); OFCHECK_EQUAL(time1.getTimeZone(), +9.25); + /* check support for leap second */ + OFCHECK(time1.setTime(23, 59, 59)); + OFCHECK(time1.setTime(23, 59, 60)); + OFCHECK(!time1.setTime(23, 59, 61)); /* the "seconds" part is mandatory if time zone is present */ OFCHECK(!time2.setISOFormattedTime("10:15 -02:30")); OFCHECK(!time2.setISOFormattedTime("1015+0100")); diff --git a/ofstd/tests/txml.cc b/ofstd/tests/txml.cc index cfa44e1c..45082fd0 100644 --- a/ofstd/tests/txml.cc +++ b/ofstd/tests/txml.cc @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2011-2018, OFFIS e.V. + * Copyright (C) 2011-2020, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by @@ -37,6 +37,10 @@ "" \ "" +// we cannot run this test if the XML parser is configured for wide characters +// because the OFTest classes and macros do not support wide strings. +#ifndef _XMLWIDECHAR + OFTEST(ofstd_xmlParser) { int i = 0; @@ -78,3 +82,9 @@ OFTEST(ofstd_xmlParser) OFCHECK(rootNode.getChildNode("parent").getChildNode("child" ,2).isEmpty()); OFCHECK(rootNode.getChildNode("element").isAttributeSet("attribute")); } + +#else + +int ofstd_txml_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif \ No newline at end of file